Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 编号为1.999999999d的楼板性能_C#_Floor - Fatal编程技术网

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
,因为
十进制
对这些数字有精确的表示。A
double
则不然。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