From 7f10edcbc56f140ec3d6c606b7eec5bb13b9af44 Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Tue, 24 Mar 2026 09:16:07 +0100 Subject: [PATCH] fix From Base operation producing wrong results for fractional inputs The fractional part loop used native `+=` and `Math.pow()` with BigNumber objects, causing string concatenation instead of arithmetic addition. Replace with BigNumber `.plus()` and `.pow()` methods. Closes #2240 Co-Authored-By: Claude Opus 4.6 --- src/core/operations/FromBase.mjs | 3 +- tests/operations/index.mjs | 1 + tests/operations/tests/FromBase.mjs | 66 +++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 tests/operations/tests/FromBase.mjs diff --git a/src/core/operations/FromBase.mjs b/src/core/operations/FromBase.mjs index 4abd5c44..8e69153b 100644 --- a/src/core/operations/FromBase.mjs +++ b/src/core/operations/FromBase.mjs @@ -51,9 +51,10 @@ class FromBase extends Operation { if (number.length === 1) return result; // Fractional part + const radixBN = new BigNumber(radix); for (let i = 0; i < number[1].length; i++) { const digit = new BigNumber(number[1][i], radix); - result += digit.div(Math.pow(radix, i+1)); + result = result.plus(digit.div(radixBN.pow(i + 1))); } return result; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index f030349d..5aec5144 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -75,6 +75,7 @@ import "./tests/Float.mjs"; import "./tests/FileTree.mjs"; import "./tests/FletcherChecksum.mjs"; import "./tests/Fork.mjs"; +import "./tests/FromBase.mjs"; import "./tests/FromDecimal.mjs"; import "./tests/GenerateAllChecksums.mjs"; import "./tests/GenerateAllHashes.mjs"; diff --git a/tests/operations/tests/FromBase.mjs b/tests/operations/tests/FromBase.mjs new file mode 100644 index 00000000..9f89a1f9 --- /dev/null +++ b/tests/operations/tests/FromBase.mjs @@ -0,0 +1,66 @@ +/** + * From Base operation tests. + * + * @author Willi Ballenthin + * @copyright Crown Copyright 2026 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "From Base: binary integer", + input: "1010", + expectedOutput: "10", + recipeConfig: [ + { + op: "From Base", + args: [2], + }, + ], + }, + { + name: "From Base: binary fraction", + input: "10.1", + expectedOutput: "2.5", + recipeConfig: [ + { + op: "From Base", + args: [2], + }, + ], + }, + { + name: "From Base: hex fraction", + input: "a.8", + expectedOutput: "10.5", + recipeConfig: [ + { + op: "From Base", + args: [16], + }, + ], + }, + { + name: "From Base: octal integer", + input: "77", + expectedOutput: "63", + recipeConfig: [ + { + op: "From Base", + args: [8], + }, + ], + }, + { + name: "From Base: octal fraction", + input: "7.4", + expectedOutput: "7.5", + recipeConfig: [ + { + op: "From Base", + args: [8], + }, + ], + }, +]);