Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.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#中的浮点运算不精确?_C#_Floating Point - Fatal编程技术网

为什么C#中的浮点运算不精确?

为什么C#中的浮点运算不精确?,c#,floating-point,C#,Floating Point,为什么下面的程序打印它打印的内容 class Program { static void Main(string[] args) { float f1 = 0.09f*100f; float f2 = 0.09f*99.999999f; Console.WriteLine(f1 > f2); } } 输出为 false 浮点的精度只有这么多位数。如果您看到f1==f2,那是因为任何差异都需要比32位浮点所能表示的

为什么下面的程序打印它打印的内容

class Program
{
    static void Main(string[] args)
    {
        float f1 = 0.09f*100f;
        float f2 = 0.09f*99.999999f;

        Console.WriteLine(f1 > f2);
    }
}
输出为

false

浮点的精度只有这么多位数。如果您看到f1==f2,那是因为任何差异都需要比32位浮点所能表示的精度更高的精度


我建议您阅读

最主要的是,这不仅仅是.Net:它是内存中的一个限制。精度仅此而已


当你考虑到它甚至不是以10为基数时,你也可以从相对简单的数字中得到一些乐趣。例如,0.1在用二进制表示时是一个重复的十进制数。

在这种特殊情况下,这是因为.09和.99999不能用精确的二进制表示(同样,1/3也不能用精确的十进制表示)。例如,0.111111111111111111111基2是0.99999986721038818359375基10。将1与上一个二进制值相加,以0.11111111为基数的2是以0.99999046432568359375为基数的10。没有精确表示0.999999的二进制值。浮点精度还受到分配用于存储指数和尾数小数部分的空间的限制。此外,与整数类型一样,浮点可以溢出其范围,尽管其范围大于整数范围

在XCODEL调试器中运行此C++代码,

float myFloat=0.1

显示myFloat的值为0.10000001。它被关闭了0.000000001。不是很多,但是如果计算有几个算术运算,不精确性可能会增加

加利福尼亚州立大学索诺玛分校的鲍勃·普兰茨(已退休)在《x86-64汇编语言与GNU/Linux计算机组织概论》第14章中对浮点进行了很好的解释。以下以该章为基础

浮点类似于科学记数法,其中一个值存储为大于或等于1.0且小于2.0(尾数)的混合数,乘以另一个数的某个幂(指数)。浮点使用基数2而不是基数10,但在Plantz给出的简单模型中,为了清晰起见,他使用基数10。想象一个系统,其中两个存储位置用于尾数,一个位置用于指数*的符号(0表示+和1表示-),一个位置用于指数。现在加上0.93和0.91。答案是1.8,而不是1.84

9311表示0.93,或9.3乘以10的-1

9111表示0.91,或9.1乘以10的-1

精确的答案是1.84,或1.84乘以10乘以0,如果我们有5个位置,则为18400,但是,只有4个位置,答案是1800,或1.8乘以10乘以0,或1.8。当然,浮点数据类型可以使用四个以上的存储位置,但位置的数量仍然有限

精度不仅受到空间的限制,而且“二进制中分数值的精确表示仅限于二的逆幂和。”(Plantz,同前)

0.11100110(二进制)=0.89843750(十进制)

0.11100111(二进制)=0.90234375(十进制)

二进制中没有0.9十进制的精确表示。即使把分数带到更多的地方也不起作用,因为你会一直在右边重复1100

刚开始编程的程序员通常认为浮点运算更重要 比整数精确。的确,即使加上两个非常大的 整数可能导致溢出。乘法运算使它更有可能发生 结果将非常大,因此溢出。什么时候用 对于两个整数,C/C++中的/运算符导致小数部分 迷路。然而。。。浮点表示法有自己的特点 一组错误。(Plantz,同前)


*浮点数表示数字的符号和指数的符号。

你为什么不自己试试呢?我试过了,我只是想知道为什么我看到了我看到的。可能重复的可能重复的+1为什么,为什么我在点击提交按钮后看到有人发布了链接P+1 Michael是正确的,C#float只有7位精度,99.99999f有8位精度。这不是C#特有的。单精度IEEE-754浮点将仅为32位,这将提供大约7位小数精度。如果你想得到更好的答案,可以使用double。double只是把问题再推几位。您真正想要的是像QD库中的那样的四倍频(请参阅)。那里也有一个任意精度的库。