为什么在C#和JavaScript中处理具有许多有效数字的数字会有所不同?

时间:2015-05-27 06:57:11

标签: javascript c# ieee-754

如果JavaScript的号码和C#的双倍指定相同(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

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

3 个答案:

答案 0 :(得分:3)

这里有很多问题......

您使用long代替double。你需要写:

double x = 1234123412341234123.0;

var x = 1234123412341234123.0;

另一个问题是,在将double转换为string之前,.NET会将Console.ToString()舍入为15位数(因此,例如在使用string str = x.ToString("f"); // 1234123412341230000.00 打印之前)。

例如:

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

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

在内部,数字仍为17位,只显示为15。

如果你这样做,你可以看到它:

NSLog

答案 1 :(得分:2)

数字的处理方式不同,它们的显示方式不同。

.NET显示带有15位有效数字的数字,而JavaScript显示带有17位有效数字。 double的表示可以包含15-17个有效数字,具体取决于它包含的数字。 .NET仅显示该数字始终支持的位数,而JavaScript显示所有数字,但精度限制可能会显示。

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

在示例中将double转换为long将绕过.NET显示双精度的方式。数字将被转换而不会隐藏精度限制的舍入,因此在这种情况下,您会看到double中的实际值。不存在超过第17位的零的原因是该值以二进制形式存储,而不是十进制形式。

答案 2 :(得分:1)

免责声明:这是基于标准wikipedia page

根据标准的维基百科页面,它定义了decimal64应具有16位精度。

过去是实施者决定应该用附加数字做什么。

所以你可能会说标准没有明确规定,但是这些数字的设计并不符合标准规范。两种语言都有处理更大数字的方法,因此这些选项可能更适合您。