为什么有很多有效数字的数字在c#和JavaScript中处理方式不同?

Why are numbers with many significant digits handled differently in C# and JavaScript?

本文关键字:JavaScript 处理 方式不 有效数字 数字 为什么      更新时间:2023-09-26

如果JavaScript的Number和c#的double被指定为相同的(IEEE 754),为什么有许多有效数字的数字处理方式不同?

var x = (long)1234123412341234123.0; // 1234123412341234176   - C#
var x =       1234123412341234123.0; // 1234123412341234200   - JavaScript

我不关心IEEE 754不能表示数字1234123412341234123。我关心的事实是,这两种实现对不能用完全精度表示的数字的作用是不同的。

这可能是因为IEEE 754没有规定,一个或两个实现都有缺陷,或者它们实现了IEEE 754的不同变体。

这个问题与c#中浮点输出格式的问题无关。我输出的是64位整数。考虑以下内容:

long x = 1234123412341234123;
Console.WriteLine(x); // Prints 1234123412341234123
double y = 1234123412341234123;
x = Convert.ToInt64(y);
Console.WriteLine(x); // Prints 1234123412341234176

相同的变量打印不同的字符串,因为值不同。

这里有很多问题…

您正在使用long而不是double。你需要写:

double x = 1234123412341234123.0;

var x = 1234123412341234123.0;

另一个问题是。net在将double s转换为string之前将其舍入到15位数字(因此在例如用Console.ToString()打印它之前)。

例如:

string str = x.ToString("f"); // 1234123412341230000.00

参见https://stackoverflow.com/a/1658420/613130

内部号码仍然是17位,只是显示为15位。

你可以看到如果你执行a:

string str2 = x.ToString("r"); // 1.2341234123412342E+18

数字没有不同的处理方式,只是显示方式不同。

。NET显示15位有效数字,而JavaScript显示17位有效数字。根据所包含的数字,双精度数的表示可以包含15-17位有效数字。. net只显示该数字保证始终支持的位数,而JavaScript显示所有数字,但可能会出现精度限制。

。. NET在指数为15时开始使用科学计数法,而JavaScript在指数为21时开始使用科学计数法。这意味着JavaScript将显示18到20位的数字,最后用零填充。

在您的示例中将double转换为long将绕过。net显示double的方式。该数字将被转换为没有隐藏精度限制的四舍五入,因此在本例中,您将看到双精度型中的实际值。第17位之后不只有0的原因是该值是以二进制形式存储的,而不是十进制形式。

免责声明:这是基于标准维基百科页面

根据该标准的维基百科页面,它定义了十进制64应该有16位的精度。

在此之后,应该由实现者决定如何处理这些额外的数字。

所以你可能会说标准没有详细说明,但这些数字的设计无论如何都不符合标准规范。两种语言都有处理更大数字的方法,所以这些选项可能更适合您。