如果a和b都是整数,则想知道以下断言是否正确> 0.在这种情况下,浮点数精度会导致问题吗?
assert(a%b || floor(a/(double)b)*b==a);
答案 0 :(得分:8)
如果条件的第一部分为假,则a
是b
的倍数。
整数转换为double
通常是精确的(如果double
是IEEE 754的二进制64,则对于最大为2 53 的整数是精确的。假设这些条件,a/(double)b
是double
最接近a
的实际除以b
。由于实际结果是一个低于2 53 的整数,因此它是完全可表示的,因此不会发生舍入(换句话说,浮点除法是精确的)。
floor()
应用于表示整数的double
,返回相同的整数。
浮点乘法与除法的原因相同,并且恰好产生a
。
结论:assert
中的条件始终为真,a
和b
之间的条件为-2 53 和2 53 ,对于将double
实现为binary64的平台,有或没有过多的精度。
答案 1 :(得分:0)
对于64位整数,这是不正确的。右边需要对a,b是正确的,其中a是b的整数倍。如果a,b <= 2 ^ 53,那么两者都可以转换为double而没有舍入误差,a /(double)b将计算精确结果,并且一切都会好的。
但如果是&gt; 2 ^ 53,然后将a转换为double可以将结果向下舍入。然后一个/(双)b可能比精确结果小一点,floor()将它向下舍入,结果将是错误的。断言失败的一个例子是
long long a = (1LL << 53) + 1;
long long b = a / 3;
如果您使用了float,那么
断言(a%b || floor(a /(float)b)* b == a);
会因为更小的值而失败。