如果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
同一个变量打印不同的字符串,因为值不同。
答案 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位精度。
过去是实施者决定应该用附加数字做什么。
所以你可能会说标准没有明确规定,但是这些数字的设计并不符合标准规范。两种语言都有处理更大数字的方法,因此这些选项可能更适合您。