Skip to content

Commit 7f10edc

Browse files
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 <noreply@anthropic.com>
1 parent b0fa1f8 commit 7f10edc

3 files changed

Lines changed: 69 additions & 1 deletion

File tree

src/core/operations/FromBase.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,10 @@ class FromBase extends Operation {
5151
if (number.length === 1) return result;
5252

5353
// Fractional part
54+
const radixBN = new BigNumber(radix);
5455
for (let i = 0; i < number[1].length; i++) {
5556
const digit = new BigNumber(number[1][i], radix);
56-
result += digit.div(Math.pow(radix, i+1));
57+
result = result.plus(digit.div(radixBN.pow(i + 1)));
5758
}
5859

5960
return result;

tests/operations/index.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import "./tests/Float.mjs";
7575
import "./tests/FileTree.mjs";
7676
import "./tests/FletcherChecksum.mjs";
7777
import "./tests/Fork.mjs";
78+
import "./tests/FromBase.mjs";
7879
import "./tests/FromDecimal.mjs";
7980
import "./tests/GenerateAllChecksums.mjs";
8081
import "./tests/GenerateAllHashes.mjs";
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* From Base operation tests.
3+
*
4+
* @author Willi Ballenthin
5+
* @copyright Crown Copyright 2026
6+
* @license Apache-2.0
7+
*/
8+
import TestRegister from "../../lib/TestRegister.mjs";
9+
10+
TestRegister.addTests([
11+
{
12+
name: "From Base: binary integer",
13+
input: "1010",
14+
expectedOutput: "10",
15+
recipeConfig: [
16+
{
17+
op: "From Base",
18+
args: [2],
19+
},
20+
],
21+
},
22+
{
23+
name: "From Base: binary fraction",
24+
input: "10.1",
25+
expectedOutput: "2.5",
26+
recipeConfig: [
27+
{
28+
op: "From Base",
29+
args: [2],
30+
},
31+
],
32+
},
33+
{
34+
name: "From Base: hex fraction",
35+
input: "a.8",
36+
expectedOutput: "10.5",
37+
recipeConfig: [
38+
{
39+
op: "From Base",
40+
args: [16],
41+
},
42+
],
43+
},
44+
{
45+
name: "From Base: octal integer",
46+
input: "77",
47+
expectedOutput: "63",
48+
recipeConfig: [
49+
{
50+
op: "From Base",
51+
args: [8],
52+
},
53+
],
54+
},
55+
{
56+
name: "From Base: octal fraction",
57+
input: "7.4",
58+
expectedOutput: "7.5",
59+
recipeConfig: [
60+
{
61+
op: "From Base",
62+
args: [8],
63+
},
64+
],
65+
},
66+
]);

0 commit comments

Comments
 (0)