この解答例はChatGPTによって生成されています,正しいかは自己判断で。
BFE.devでのAI解答例 - JavaScript コーディング問題
127. BigDecimal 引き算
解法:
BigInt の場合と同様に、桁上がりの扱いが厄介な問題です。以下の手順に従って実装することができます。
- 符号を正規化し、引き算対象の二つの文字列の整数部分と小数部分を抽出する。
- 二つの小数部分を桁が合うように調整する。
- 二つの整数部分を末尾から順に引き算し、桁上がりを考慮する。
- 桁上がりがあった場合、繰り上がりがなくなるまで繰り返す。
- 符号、整数部分、小数部分を結合して、最終的な結果を作成する。
- 後続ゼロを取り除く。
以下は実装例です。
function subtract(s1, s2) {
const [sign1, intStr1, decimal1] = normalize(s1)
const [sign2, intStr2, decimal2] = normalize(s2)
let intRes = ''
let decRes = ''
if (compareAbs(s1, s2) === -1) { // s2 > s1
[sign1, sign2] = [sign2, sign1]
;[intStr1, intStr2] = [intStr2, intStr1]
;[decimal1, decimal2] = [decimal2, decimal1]
}
let borrow = 0
let i = intStr1.length - 1
let j = intStr2.length - 1
while (i >= 0 || j >= 0) {
const num1 = i >= 0 ? Number(intStr1[i]) : 0
const num2 = j >= 0 ? Number(intStr2[j]) : 0
let diff = num1 - num2 - borrow
if (diff < 0) {
diff += 10
borrow = 1
} else {
borrow = 0
}
intRes = `${diff}${intRes}`
i--
j--
}
// Trim leading zeros
intRes = intRes.replace(/^0+/, '')
const maxLenDec = Math.max(decimal1.length, decimal2.length)
let d1 = decimal1.padEnd(maxLenDec, '0')
let d2 = decimal2.padEnd(maxLenDec, '0')
for (let i = maxLenDec - 1; i >= 0; i--) {
let diff = Number(d1[i]) - Number(d2[i]) - borrow
if (diff < 0) {
diff += 10
borrow = 1
} else {
borrow = 0
}
decRes = `${diff}${decRes}`
}
if (borrow === 1) {
intRes = subtract(`1${intRes}`, '1')
}
const resSign = sign1 === '+' ? '' : '-'
let res = `${intRes}${decRes ? `.${decRes}` : ''}`
res = trimTrailingZeros(res)
return resSign + res
}
function normalize(numStr) {
let sign = ''
if (numStr[0] === '-' || numStr[0] === '+') {
sign = numStr[0]
numStr = numStr.slice(1)
}
let [intStr, decimal] = numStr.split('.')
intStr = intStr || '0'
decimal = decimal || ''
return [sign, intStr, decimal]
}
function trimTrailingZeros(numStr) {
return numStr.replace(/\.?0+$/, '')
}
function compareAbs(numStr1, numStr2) {
const [_, intStr1, decimal1] = normalize(numStr1)
const [__, intStr2, decimal2] = normalize(numStr2)
if (intStr1.length !== intStr2.length) {
return intStr1.length - intStr2.length
}
for (let i = 0; i < intStr1.length; i++) {
const diff = Number(intStr1[i]) - Number(intStr2[i])
if (diff !== 0) {
return diff
}
}
if (decimal1.length !== decimal2.length) {
return decimal1.length - decimal2.length
}
for (let i = 0; i < decimal1.length; i++) {
const diff = Number(decimal1[i]) - Number(decimal2[i])
if (diff !== 0) {
return diff
}
}
return 0
}