这是我不理解的代码的一部分:
byte b1 = (byte)(64 / 0.8f); // b1 is 79
int b2 = (int)(64 / 0.8f); // b2 is 79
float fl = (64 / 0.8f); // fl is 80
为什么前两个计算一个一个?我应该如何执行此操作,以便快速正确?
编辑:我需要在字节中的结果
这是我不理解的代码的一部分:
byte b1 = (byte)(64 / 0.8f); // b1 is 79
int b2 = (int)(64 / 0.8f); // b2 is 79
float fl = (64 / 0.8f); // fl is 80
为什么前两个计算一个一个?我应该如何执行此操作,以便快速正确?
编辑:我需要在字节中的结果
编辑:不完全正确,请参阅: 为什么除法结果会根据演员类型而有所不同? (跟进)
舍入问题:通过转换为byte / int,您将剪切小数位。
但 64 / 0.8
不应该导致任何小数位?错误:由于浮点数的性质,0.8f不能完全像内存中的那样表示;它被存储为接近0.8f的东西(但不完全是)。看到 浮点不准确的例子 或类似的线程。因此,计算结果不是80.0f,而是79.xxx,其中xxx接近1但仍然不是一个。
您可以通过在Visual Studio中的立即窗口中键入以下内容来验证这一点:
(64 / 0.8f)
80.0
(64 / 0.8f) - 80
-0.0000011920929
100 * 0.8f - 80
0.0000011920929
你可以通过使用舍入来解决这个问题:
byte b1 = (byte)(64 / 0.8f + 0.5f);
int b2 = (int)(64 / 0.8f + 0.5f);
float fl = (64 / 0.8f);
在这样的情况下,我担心快速和正确是不一致的。
二进制浮点运算几乎总是会产生小错误,因为 我们的CPU架构中的底层表示。因此,在初始表达式中,实际上得到的值比数学上正确的值小一点。如果你期望一个整数作为特定数学运算的结果而你得到的东西非常接近它,你可以使用 Math.Round(Double, MidpointRounding)
方法执行正确的舍入并补偿小错误(并确保你选择 该 MidpointRounding
你期望的策略)。
只需将结果转换为类型 byte
要么 int
不做舍入 - 它只是切断了小数部分(甚至 1.99999f
会变成 1
当你把它投射到这些类型时)。
十进制浮点运算速度较慢且占用内存较多,但不会导致这些错误。要执行它,请使用 decimal
文字而不是 float
文字(例如 64 / 0.8m
)。
经验法则 是:
decimal
。double
。float
。要理解该问题,您需要了解浮点表示和操作的基础知识。
0.8f无法使用浮点数在内存中精确表示。
在数学中,64 / 0.8等于80。 在浮点算术中,60 / 0.8约等于80。
将浮点数转换为整数或字节时,仅保留数字的整数部分。在您的情况下,浮点除法的不精确结果略小于80,因此转换为整数产生79。
如果你需要一个整数结果,我建议你舍入结果而不是转换它。 一种方法是使用以下函数,通过舍入到最接近的整数转换为整数:
Convert.ToInt32(64/0.8f);