为什么Java的LONG_MAX与Vue的axios数据不同?如何解决?

huangapple go评论80阅读模式
英文:

Why java LONG_MAX is not same with vue axios data?? How to fix that?

问题

以下是翻译好的内容:

后端 API:

@RequestMapping(mapping = "/get-long-max", requestMethod = RequestMethod.GET)
private long getLONG() {
  System.out.println(Long.MAX_VALUE);
  return Long.MAX_VALUE;
}

前端:

getLongValue() {
  return axios.get('http://localhost:8080/get-long-max.do').
  then(response => {
    console.log(response.data.payload);
    return response.data.payload;
  }).catch(error => console.error(error));
}

每当我从客户端调用这个函数时,Long_MAX 在两端的值并不相同。
Java 的 system.out 显示的值是 9223372036854775807,而前端的值是 9223372036854776000

英文:

I am using java 8 for the backend and Vue CDN(2.5.16) for the front-end. My codes are giving below

BACKEND API:

@RequestMapping(mapping = "/get-long-max", requestMethod = RequestMethod.GET)
private long getLONG() {
  System.out.println(Long.MAX_VALUE);
  return Long.MAX_VALUE;
}

Front-end:

getLongValue() {
  return axios.get('http://localhost:8080/get-long-max.do').
  then(response => {
    console.log(response.data.payload);
    return response.data.payload;
  }).catch(error => console.error(error));
}

Whenever I call the function from the client-side. The Long_MAX is not the same for both ends.
Java system.out shows the value 9223372036854775807 and the front end value is 9223372036854776000.
为什么Java的LONG_MAX与Vue的axios数据不同?如何解决?

Please help to fix it. Thanks in advance.

Update 1:

When I hit the URL directly on the browser it seems ok 为什么Java的LONG_MAX与Vue的axios数据不同?如何解决?

答案1

得分: 2

所有值超过正负2^53的长整型都会受到影响,因为在 JavaScript 中,并不存在'long'这个概念,也不在 JSON 中存在,一切都是使用double

修复方法之一是始终传递double,在这种情况下,Java 那一侧也将显示 9223372036854776000(在2^53之上和-2^53之下,double 类型能够表示的任意两个连续数字之间的距离大于1.0,即不再能表示每个整数值)。

另一种方法是确保所有的数值需求都适应于 -2^53 到 +2^53 范围内。

第三种方法是将所有数据都传递为字符串。

你在纯粹的 Java 代码中也可以看到这一点:

long x = Long.MAX_VALUE;
double d = x;
System.out.println(x);
System.out.println(d);
System.out.println((long) d);

这将打印出:

9223372036854775807
9.223372036854776E18
9223372036854775807

<del>我本来预期最后一个输出会是 9223372036854776000,但我猜 2^63-1 恰好是可以表示的 double 值</del>(编辑:见下文),但要注意第二个输出是以科学计数法表示的数字,你在 JavaScript 中看到的数字也是如此。还请注意这段代码:

long x = Long.MAX_VALUE - 1;
double d = x;
System.out.println(x);
System.out.println(d);
System.out.println((long) d);

这将打印出:

9223372036854775806
9.223372036854776E18
9223372036854775807

注意第一个和第三个输出之间的差异。<del>因此,尽管我无法解释为什么你会看到 9223372036854776000</del>,但这几乎肯定是由于浮点数/双精度数转换和呈现问题,而且 无法修复 这个问题;你无法在长整型和双精度数/浮点数之间进行无损转换,正如第二个示例所示,因此解决方案不是这样做,但 JSON 中不存在long,所以你要么避开这个问题范围(在±2^53 之上和之下),要么以字符串形式传输这些数据。

编辑:

我解释了代码示例中的奇怪现象。事实证明,双精度数值确实是 9223372036854776000。然而,当你将该数字强制转换为长整型时,你会再次得到 9223372036854775807 - 这在后来是显而易见的,因为这是最接近的长整型值(也是最大的长整型值)。实际上,long big = (long) 1e300; 也会得到这个值。至于 @Tuhin47 - 你需要使用其他方式测试你的数字从 Java 代码到 JavaScript 代码的转换路径:这个数字(9223372036854775807)具有这样的特性,即如果你将它转换为双精度数,然后再转回长整型,你会得到相同的数字,这意味着你可能会认为它是有效的,但实际上并非如此。使用 9223372036854775806,它具有这样的特性,即如果你将它转换为双精度数,然后再转回,你会得到一个不同的数字。

英文:

All longs whose value exceeds plus or minus 2^53 will suffer from this, as the concept 'long' isn't a thing in javascript land / not a thing in JSON, it's all double over there.

One fix is to always pass double, at which point the java side, too, would show 9223372036854776000 (above 2^53 and below -2^53, the distance between any 2 consecutive numbers that the double type can represent is greater than 1.0, i.e. not every integral number is representable any more).

Another is to ensure all your numeric needs fit within -2^53 and +2^53.

A third is to pass all data a strings.

You can see this purely in java code, too:

long x = Long.MAX_VALUE;
double d = x;
System.out.println(x);
System.out.println(d);
System.out.println((long) d);

this prints:

9223372036854775807
9.223372036854776E18
9223372036854775807

<del>I was expecting that last one to be 9223372036854776000, but I guess 2^63-1 does so happen to be a representable double</del> (EDIT: See below), but note that the second print is the e-notation form of the number you are seeing in javascript. Also note this snippet:

long x = Long.MAX_VALUE - 1;
double d = x;
System.out.println(x);
System.out.println(d);
System.out.println((long) d);

this prints:

9223372036854775806
9.223372036854776E18
9223372036854775807

Note how there is now a difference between the first and third print. <del>So, whilst I have no explanation for why you are seeing 9223372036854776000</del>, it's almost certainly because of float/double conversion and rendering issues, and there is no way to fix that; you cannot losslessly convert a long to double or float and back to long, as the second snippet shows, so the solution is not to do that, but, long does not exist in JSON, so you'd have to either avoid the problem range (above and below ±2^53) or transit this data in string form.

EDIT:

I figured out the weirdness inherent in the code examples. Turns out, the double value is in fact 9223372036854776000. However, when you cast that number to a long, you get 9223372036854775807 again - this is in hindsight obvious, as that's the closest long value (it is also the highest possible long value). In fact, long big = (long) 1e300; would also get you that value. As for @Tuhin47 - you need to test the 'path' that your number takes from your java code to your javascript code with something else: This number (9223372036854775807) has the property that if you convert it to a double and then back to a long, that you get the same number back, which means you may think it's working when it really isn't. Use 9223372036854775806, which has the property that if you convert it to a double and back, that you get a different number out.

huangapple
  • 本文由 发表于 2020年10月17日 21:20:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/64402932.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定