我在使用可添加的可浮动浮点数时发现了一些非常奇怪的东西。请使用以下代码:
float? a = 2.1f;
float? b = 3.8f;
float? c = 0.2f;
float? result =
(a == null ? 0 : a)
+ (b == null ? 0 : b)
+ (c == null ? 0 : c);
float? result2 =
(a == null ? 0 : a.Value)
+ (b == null ? 0 : b.Value)
+ (c == null ? 0 : c.Value);
result
为6.099999
,而result2
为6.1
。我很幸运能够偶然发现这一点,因为如果我更改a
,b
和c
的值,行为通常会显示正确。其他算术运算符或其他可空值类型也可能发生这种情况,但这是我能够重现的情况。我不明白为什么float
中float?
的隐式强制转换在第一种情况下无效。我或许可以理解,如果条件的另一边是int
,它是否试图获得0
值,但这似乎不是正在发生的事情。鉴于result
仅对某些浮动值组合显示不正确,我假设这是多次转换的某种舍入问题(可能是由于装箱/拆箱或其他原因)。
有什么想法吗?
答案 0 :(得分:4)
请参阅@EricLippert的评论。
允许任何更改结果 - 让我强调一下 允许再次包括月相在内的任何 更改是否以32位精度或更高精度计算浮点数 准确性。始终允许处理器出于任何原因 决定突然开始以80位或者80位进行浮点运算 128位或任何它选择的东西,只要它大于或等于 32位精度。看到 (.1f+.2f==.3f) != (.1f+.2f).Equals(.3f) Why? 了解更多详情。
在这种情况下询问特别是导致处理器决定 在一种情况下使用更高的精度而在另一种情 游戏。它可能是任何东西。如果您需要 中的准确计算 十进制数字然后使用恰当命名的
decimal
类型。如果您需要 在浮点数中可重复的计算然后C#有两种机制 强制处理器回到32位。 (1)显式转换为(float) 不必要地,或(2)将结果存储在float数组元素中 引用类型的浮点字段。
此处的行为与Nullable类型无关。这是一个浮动的问题,从来都不是精确的,并且在处理器的突发奇想中以不同的精度计算。
一般来说,这可以归结为如果准确性很重要,最好的办法是使用float
之外的其他东西(或使用@EricLippert描述的技术强制处理器使用32位精度)。
answer from Eric Lippert on linked question也有助于了解正在发生的事情。