-3

It's relating to a problem with how JavaScript handles large (Floating-Point) numbers.

What is JavaScript's highest integer value that a number can go to without losing precision? is referring to the highest possible number. I was after a way to bypass that for getting the min and max in the example below.

var lowest = Math.min(131472982990263674, 131472982995395415);
console.log(lowest);

Wil return: 131472982990263680


To get the min and max value would it be required to write a function to suit or is there a way I can get it working with the Math.min and Math.max functions?

The closest solution I've found was this but I couldn't manage to get it working as I cannot avail of BigInt function as it's not exposed to my version.

Large numbers erroneously rounded in JavaScript

Ste
  • 1,729
  • 1
  • 17
  • 27
  • Does this answer your question? [What is JavaScript's highest integer value that a number can go to without losing precision?](https://stackoverflow.com/questions/307179/what-is-javascripts-highest-integer-value-that-a-number-can-go-to-without-losin) – ASDFGerte Feb 13 '21 at 23:11
  • 1
    Use a BigInt library if you don't have access to the native BigInt. – Ivar Feb 13 '21 at 23:15
  • No, I don't want to know the highest number. Man, it's a tough crowd. A downvote on the question already. It's quite clear what I was after. – Ste Feb 13 '21 at 23:16
  • @Ste "*No, I don't want to know the highest number*" then how do you intend to fix your issue when it's intimately tied with what the highest value is? – VLAZ Feb 13 '21 at 23:17
  • 2
    Math.* methods works with values less then or equals to Number.MAX_SAFE_INTEGER only. If you want to operate on BigInts, you can use https://github.com/peterolson/BigInteger.js as polyfill if BigInt is not available natively – fxnoob Feb 13 '21 at 23:19
  • then do const bigIntMax = (...args) => args.reduce((m, e) => e > m ? e : m); const bigIntMin = (...args) => args.reduce((m, e) => e < m ? e : m); or something.. – fxnoob Feb 13 '21 at 23:20
  • The highest possible number. That's what the thread is referring to. My question is simple. Is it possible to get the max and min in the example I've given? – Ste Feb 13 '21 at 23:21
  • Yes, you can wrap it in a function, parse the source code (if the engine allows you to), and read the values from there. – ASDFGerte Feb 13 '21 at 23:22
  • my answer refers to min and max value out of given numbers. read carefully – fxnoob Feb 13 '21 at 23:23
  • @Ste your example doesn't contain a value `131472982990263674` nor `131472982995395415`. Both of these are much much bigger than the max safe integer value and ***cannot*** be expressed as a JavaScript numeric. For all intents and purposes, they don't exist. Therefore, the simple answer to your simple question is "no". If you want a *useful* rather than simple answer, you'd need to actually understand your own question. – VLAZ Feb 13 '21 at 23:28
  • It's a question. I'm not meant to understand it all. Hence why it's a question. I'll see about the external library, thanks @fxnoob. I thought there may be a way to get the min and max with Vanilla JS. – Ste Feb 13 '21 at 23:31
  • 1
    "*I'm not meant to understand it all.*" but you're also not meant to refuse to understand it. – VLAZ Feb 13 '21 at 23:36
  • I am fully aware that the large numbers are a problem for JS. That has been part of the question all along. – Ste Feb 13 '21 at 23:40
  • I typically just leave in these cases, but lets make this a bit more direct: when you enter `131472982990263674` in code (a normal number literal, no `n` suffix), it will get crammed into at most an IEEE754-2019 float64 while the engine parses your code. That means 53bit mantissa, and everything more is lost. You have no influence on the parser. As mentioned above, "is it possible?" - yes, typically, engines allow you to read the source code as a string yourself (e.g. `Function.prototype.toString`), but then it's better to just have it as a string to begin with. – ASDFGerte Feb 13 '21 at 23:42
  • BigInt has broad support across all major supported browsers including mobile browsers, in addition to node.js. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt. What specific version are you targeting that doesn't support BigInt? – Trentium Feb 14 '21 at 16:47

2 Answers2

0

You can try to convert the numbers to BigInt:

const n1 = BigInt("131472982990263674"); // or const n1 = 131472982990263674n;
const n2 = BigInt("131472982995395415"); // or const n1 = 131472982995395415n;

Then find the min and max using this post:

const n1 = BigInt("131472982990263674");
const n2 = BigInt("131472982995395415");

function BigIntMinAndMax (...args){
  return args.reduce(([min,max], e) => {
     return [
       e < min ? e : min, 
       e > max ? e : max,
     ];
  }, [args[0], args[0]]);
};

const [min, max] = BigIntMinAndMax(n1, n2);
console.log(`Min: ${min}`);
console.log(`Max: ${max}`);
Ricardo Rocha
  • 14,612
  • 20
  • 74
  • 130
0

Math.min and Math.max are working just fine.

When you write 131472982990263674 in a JavaScript program, it is rounded to the nearest IEEE 754 binary64 floating-point number, which is 131472982990263680.

Written in hexadecimal or binary, you can see that 131472982990263674 = 0x1d315fb40b2157a = 0b111010011000101011111101101000000101100100001010101111010 takes 56 bits of precision to represent. If you round that to the nearest number with only 53 bits of precision, what you get is 0b111010011000101011111101101000000101100100001010110000000 = 0x1d315fb40b21580 = 131472982990263680 (significant bits in bold).

Similarly, when you write 131472982995395415 in JavaScript, what you get back is 131472982995395410.

So when you write the code Math.min(131472982990263674, 131472982995395415), you pass the numbers 131472982990263680 and 131472982995395410 into the Math.min function. Given that, it should come as no surprise that Math.min returns 131472982990263680.

> 131472982990263674
131472982990263680
> 131472982995395415
131472982995395410
> Math.min(131472982990263674, 131472982995395415)
131472982990263680

It's not clear what your original goal is.

  • Are you given two JavaScript numbers to begin with, and are you trying to find the min or max?

    If so, Math.min and Math.max are the right thing.

  • Are you given two strings, and are you trying to order them by the numbers they represent?

    If so, it depends on the notation you want to support.

    If you only want to support decimal notation for integers (with no scientific notation, like 123e4), then you can simply chop leading zeros and compare the strings lexicographically with < or > in JavaScript.

    > function strmin(x, y) { return x < y ? x : y }
    > strmin("131472982990263674", "131472982995395415")
    '131472982990263674'
    

    If you want to support arbitrary-precision decimal notation (including non-integers and perhaps scientific notation), and you want to maintain distinctions between, for instance, 1.00000000000000001 and 1.00000000000000002, then you probably want a general arbitrary-precision decimal arithmetic library.

  • Are you trying to do arithmetic with integers in a range that might exceed 2⁵³, and need the computation to be exact, requiring >53 bits of precision?

    If so, you may need some kind of wider-precision or arbitrary-precision arithmetic than JavaScript numbers alone provide, like bigint recently added to JavaScript.

    If you only need a little more than 53 bits of precision, as is often the case inside numerical algorithms for transcendental elementary functions, there's also T.J. Dekker's algorithm for extending (say) binary64 arithmetic into double-binary64 or “double-double” arithmetic: a double-binary64 number is the sum + of two binary64 floating-point numbers and , where typically holds the higher-order bits and holds the lower-order bits so together they can store 106 bits of precision.

Floating Pundit
  • 299
  • 2
  • 6