C# 编号为1.999999999d的楼板性能
看看这种情况:C# 编号为1.999999999d的楼板性能,c#,floor,C#,Floor,看看这种情况: var number1 = Math.Floor(1.9999999999999998d); // the result is 1 var number2 = Math.Floor(1.9999999999999999d); // the result is 2 在两种情况下,结果都应为1。我知道这是一个非常不可能的情况,但有可能发生。与Math.Truncate方法和(int)强制转换相同的ocurr 为什么会发生这种情况?很多数字都没有精确的double表示法 距离1.99
var number1 = Math.Floor(1.9999999999999998d); // the result is 1
var number2 = Math.Floor(1.9999999999999999d); // the result is 2
在两种情况下,结果都应为1。我知道这是一个非常不可能的情况,但有可能发生。与Math.Truncate
方法和(int)
强制转换相同的ocurr
为什么会发生这种情况?很多数字都没有精确的
double
表示法
距离1.99999999999999999
最近的double
数字是2
,因此编译器将其四舍五入
在使用Math.Floor
功能之前,请尝试打印它
但是,距离1.999999999999988
最近的仍然是1.something
,因此Floor
发出1
同样,在功能Floor
之前打印数字就足够了,这样就可以看到它们实际上不再是代码中输入的数字
编辑:要以最高精度打印数字:
double a1 = 1.9999999999999998;
Console.WriteLine(a1.ToString("G17"));
// output : 1.9999999999999998
double a2 = 1.9999999999999999;
Console.WriteLine(a2.ToString("G17"));
// output : 2
由于双精度并不总是精确到17位有效数字(包括小数点前的第一位),因此默认值
ToString()
会将其四舍五入到16位有效数字,因此在这种情况下,也会将其四舍五入到2
,但仅在运行时,不是在编译时。如果您将文本值放入另一个变量中,那么您就会明白为什么:
var a1 = 1.9999999999999998d; // a1 = 1.9999999999999998d
var number1 = Math.Floor(a1);
Console.WriteLine(number1); // 1
var a2 = 1.9999999999999999d; // a2 = 2
var number2 = Math.Floor(a2);
Console.WriteLine(number2); // 2
至于原因-这必须与
double
和编译器决定对给定的文本使用什么值有关。如果你只做,比如说,Console.Write(1.9999999999999d),会发生什么代码>?这里的问题是1.9999999999999d
已经是2
1.9999999999d
不能用可用位表示,因此它在内存中变成2.0d
,这就是Floor()
作为参数接收的内容。Math.Floor(1.99999999999999m)
是1
,因为十进制
对这些数字有精确的表示。Adouble
则不然。double的精度仅为15-16位。在您的例子中,它在编译时被四舍五入,1.9999999999999999d
被转换成具有确切值2
(1.9999999999999d==2.0d
为true
)。当然,在这之后,结果就如预期的一样了。@Jeroenmoster,没错,但编译器为什么以及如何做到这一点-不知道tbh。为什么不选择上一个值?什么是“上一个值”2
是最接近的可表示值,向上舍入。您是否希望它向下取整为1.999999999999 8
?“那没什么意义,”杰罗·莫斯特,“向上舍入”-好吧,为什么向上?这个决定背后可能有原因,但我无法回答这个问题。IEEE 754和/或C#语言规范,等等。我不能很快找到规范的相关部分,但是规则已经存在了。。。某处。(并非编译器必须遵循这些规则;特别是,由于x87扩展了80位精度,在编译时和运行时的双重
求值规则是出了名的不同。)打印没有帮助,因为它无法提供准确的表示,例如Console.WriteLine(1.999999999999999)
,我得到了2
,但它产生了1
<但是,code>ToString(“r”)
可能会有所帮助,并显示数字的内部表示形式实际上是1.9999999999989
。