有谁可以告诉我为什么这两个模数计算产生两种不同的结果?我只是需要责怪某人或某事而不是我,因为我找不到这个错误。
public void test1()
{
int stepAmount = 100;
float t = 0.02f;
float remainder = t % (1f / stepAmount);
Debug.Log("Remainder: " + remainder);
// Remainder: 0.01
float fractions = 1f / stepAmount;
remainder = t % fractions;
Debug.Log("Remainder: " + remainder);
// Remainder: 0
}
使用VS-2017 V15.3.5
答案 0 :(得分:8)
我最好的选择是,这是由于运行时必须以比所涉及的类型更高的精度执行浮点运算,然后在分配时将结果截断为类型的精度:
第12.1.3节中的CLI规范规定了浮点数(float和double)在存储位置使用时的精确精度。但是,当浮点数用于其他位置(如执行堆栈,参数返回值等)时,它允许超出精度。使用的精度是运行时和底层硬件的精度。这种额外的精度可能会导致不同机器或运行时之间浮点评估的细微差别。
来源here。
在第一个示例中,t % (1f / stepAmount)
可以完全以高于float
的精度执行,然后在将结果分配给remainder
时截断,而在第二个示例中{{1}在模数运算之前被截断并分配给1f / stepAmount
。
为什么使fractions
成为stepamount
使两个模数运算保持一致,原因是const
立即成为一个常量表达式,在处计算并截断浮点精度编译时间与编写1f / stepamount
没什么不同,这实际上使两个例子都相同。