1

在 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 为底的符​​号一样工作而没有失去精度。

Double c - 与 Float 相同。

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

问题是FloatDouble 'c''x'组是怎么回事?为什么Double 'x'组失去了精度,而Float组实际上以 10 为基数进行计算,可以说是“预期”的计算结果?想知道为什么将Double x组的数字类型声明为 F 如此彻底地改变了它的结果?

对于它的价值,我只希望十进制组给我'-0.8'的结果,而其他所有的东西都给'-0.799999997019768'。

看起来我错过了一些在计算处理方式中发生的理解链接。

4

2 回答 2

5

首先 - 这与基数 2 与基数 10 无关。您的所有值都使用基数 10 表示。此代码中不使用基数 2。

看起来我错过了一些在计算处理方式中发生的理解链接。

两者都float使用double浮点表示,这不是 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

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

如果您想真正理解这一点,那么值得阅读的一篇好文章是每个计算机科学家都应该了解的关于浮点运算的知识。大多数常见的编程语言对浮点数使用类似的表示,因此这些问题相当普遍。

于 2013-07-04T00:19:00.187 回答
0

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

在该x组中,double变量已经具有额外的精度,但是将float-type 常量放入其中很可能会导致编译器的行为略有不同,从而导致精度较低的结果。由于双打已经稍微偏离了它们应该在的位置,所以完整的double精度只是将错误向前推进。

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

哦,这一切都与基数 2 无关。

于 2013-07-04T01:05:22.047 回答