Skip to content

Commit 345bcd4

Browse files
fix(js/ts): Fix Decimal.GetBits returning incorrect mantissa after round arithmetic result (#4561)
Co-authored-by: Mangel Maxime <me@mangelmaxime.fr>
1 parent 9194bed commit 345bcd4

2 files changed

Lines changed: 18 additions & 4 deletions

File tree

src/fable-library-ts/Decimal.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,16 @@ export function fromParts(low: number, mid: number, high: number, isNegative: bo
248248

249249
export function getBits(d: Decimal) {
250250
const bitSize = 96;
251-
const decDigits = Uint8Array.from(d.c);
251+
const decStr = d.toString();
252+
const absStr = decStr[0] === "-" ? decStr.slice(1) : decStr;
253+
const dotPos = absStr.indexOf(".");
254+
const scale = dotPos < 0 ? 0 : absStr.length - dotPos - 1;
255+
const mantissaStr = absStr.replace(".", "");
256+
const decDigits = Uint8Array.from(mantissaStr, ch => ch.charCodeAt(0) - 48);
252257
const hexDigits = decimalToHex(decDigits, bitSize);
253258
const low = getInt32Bits(hexDigits, 0);
254259
const mid = getInt32Bits(hexDigits, 8);
255260
const high = getInt32Bits(hexDigits, 16);
256-
const decStr = d.toString();
257-
const dotPos = decStr.indexOf(".");
258-
const scale = dotPos < 0 ? 0 : decStr.length - dotPos - 1;
259261
const signExp = ((scale & 0x7F) << 16) | (d.s < 0 ? 0x80000000 : 0);
260262
return [low, mid, high, signExp];
261263
}

tests/Js/Main/ArithmeticTests.fs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,18 @@ let tests =
253253
d2 |> equal d
254254
d3 |> equal -d
255255

256+
testCase "Decimal GetBits works with arithmetic operations" <| fun () ->
257+
let check (d: decimal) =
258+
let bits = Decimal.GetBits(d)
259+
Decimal(bits) |> equal d
260+
261+
check (10M + 10M)
262+
check (100.5M - 0.5M)
263+
check (5M * 200M)
264+
check (-0.1M * 100M)
265+
check (2000M / 10M)
266+
check (1.5M + 0.5M)
267+
256268
testCase "Decimal abs works" <| fun () ->
257269
abs -4M |> equal 4M
258270

0 commit comments

Comments
 (0)