C#-数字变量类型-基数2/基数10表示法

本文关键字:基数 表示 C#- 变量 类型 数字 | 更新日期: 2023-09-27 18:20:59

在c#中有一件小事让我感到困惑:)

这是我的变量&结果:

decimal a1 = 0.2M;
decimal a2 = 1.0M;
a1 - a2 = -0.8
float b1 = 0.2F;
float b2 = 1.0F;
b1 - b2 = -0.8
double c1 = 0.2;
double c2 = 1.0;
c1 - c2 = -0.8
double x1 = 0.2F;
double x2 = 1.0F;
x1 - x2 = -0.799999997019768

小数-结果正如我所期望的那样,因为我知道它们以10为基数。

Float-让我很惊讶,因为我知道它在基2表示法上工作,它实际上显示了结果就好像它是以10为基数的记数法,精度不高。

双c-与Float相同。

Double x-显示我所期望的Float发生的结果。

问题是浮点双'c''x'ouble‘x’组失去了精度,而Float实际上是用基数10表示法计算的,可以说是计算的"预期"结果?想知道为什么将Double x组的数字类型声明为F会如此剧烈地改变它的输出?

就其价值而言,我只希望小数组给我"-0.8"的结果,而所有其他的结果都是"-0.7999997019768"。

看起来我错过了一些理解计算是如何处理的环节。

C#-数字变量类型-基数2/基数10表示法

首先,这与基数2与基数10无关。您的所有价值观都使用基数10表示。在此代码中未使用基数2。

看起来我错过了一些理解计算是如何处理的环节。

floatdouble都使用浮点表示数字,这不是100%准确。当显示值时,将进行四舍五入。由于float固有的精度较低,因此它被四舍五入到较少的小数点,这可以使它在某些情况下"看起来"更准确(尽管它实际上不那么精确)。

在您的情况下,"x"组和"c"组显示不同的原因是您声明的x1和x2变量如下:

double x1 = 0.2F;
double x2 = 1.0F;

实际上,这与做是一样的

float temp = 0.2f;
double x1 = temp; // Convert from float to double, which has a loss of precision
temp = 1f;
double x2 = temp; // Convert from float to double, which has a loss of precision

因此,x1x2不具有与c1c2完全相同的值。这导致了更大的精度损失,稍后,当减法发生时,这足以使打印不再舍入。

如果你想真正理解这一点,一篇很好的文章是《每个计算机科学家都应该知道浮点运算》。大多数常见的编程语言对浮点数使用类似的表示,因此这些问题相当普遍。

C#中长期以来一直存在程序员困惑的根源,即语言规范允许对浮点值执行大多数中间运算时都要使用额外的精度。编译器通常这样做是为了加快速度,因为许多处理器都是这样做的。我不太清楚具体的细节(如果我错了,有人可以随时纠正我),但b部分的计算似乎使用了这种额外的精度。

x组中,double变量已经具有额外的精度,但在其中放入float类型的常量很可能会导致编译器的行为略有不同,从而导致不太精确的结果。由于双打已经偏离了应有的位置,因此double的全精度只是将误差向前推进。

最终,C#中的浮点精度在很大程度上不是可以明确依赖的,因为编译器有很大的余地根据自己的选择进行微调,但它认为只要提供规范中规定的最小精度,就会优化得最好。

哦,这些都与2号基地无关。