Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hexadecimal-encoded constants do not respect number configuration setting [was 64-bit numerical calculation error] #3342

Open
gagmeng opened this issue Dec 26, 2024 · 4 comments · May be fixed by #3348

Comments

@gagmeng
Copy link

gagmeng commented Dec 26, 2024

hex(0x0AF076A6E6E12400 - 0x0112A88517556970)
"0x9ddce21cf8bba80"
The correct answer must be 0x9ddce21cf8bba90.

@gwhitney
Copy link
Collaborator

gwhitney commented Jan 3, 2025

By default, mathjs uses the JavaScript number type (IEEE 64-bit floating point) to represent numerical constants, even hexadecimal-notated integers. This type has only 53 bits of precision for the mantissa, and hence can only exactly represent integers in roughly the range ±2^53. The integers in your example are outside that range, leading to loss of precision and hence an approximate result.

You should be able to switch to JavaScript bigint (arbitrary-precision integer) representation to get a precise answer via:

const math = create(all, {number: 'bigint'})
const res = math.evaluate('hex(0x0AF076A6E6E12400 - 0x0112A88517556970)')

However, there is a bug in that hexadecimal-encoded numeric constants do not appear to respect the number attribute of the configuration. So changing the title of this issue to reflect that bug. I can submit a PR for this bug once my upcoming PR, also related to bigints, is merged.

@gwhitney gwhitney changed the title 64-bit numerical calculation error Hexadecimal-encoded constants do not respect number configuration setting [was 64-bit numerical calculation error] Jan 5, 2025
@josdejong
Copy link
Owner

Thanks for the clear explanation Glen. I did look into why it doesn't work for bigint, and created a PR that fixes the issue: #3348. Can you maybe have brief look at the PR?

Instead of bigint, using BigNumber will work too since it has a higher precision:

math.config({ number: "BigNumber"})

const res = math.evaluate('hex(0x0AF076A6E6E12400 - 0x0112A88517556970)') 
// 0x9ddce21cf8bba90 (correct)

@josdejong
Copy link
Owner

@gwhitney I only now see that you've also been working on a fix in #3345, I still have to review it but at first sight it looks like the two PR's are complementary.

@gwhitney
Copy link
Collaborator

Yes, I deliberately left this point alone in #3345 so that they could be handled orthogonally. I will review #3348 now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants