假设:
unsigned int a, b, c, d;
我想:
d = a * b / c;
和(a * b)可能溢出; (b / c)也可能等于零并且准确度较低。
使用64位的演员可能会让事情发挥作用,但我想知道在d中获得最准确结果的最佳方法。
有什么好的解决方案吗?
答案 0 :(得分:5)
我要么:
float
或double
并返回。答案 1 :(得分:3)
为了获得最佳准确度/精确度,您需要在分割之前进行倍增。正如你暗示的那样,你需要使用比int更多位的东西:
int64_t d = (int64_t) a * (int64_t) b;
d /= c;
你不需要两个演员,但他们可以说它更清晰。
请注意,如果c足够小,那么d仍然可以大于int。这对您来说可能是也可能不是问题。如果您确定不是,那么最后可以转换为int。
答案 2 :(得分:1)
使用float或double,在浮点运算中,允许除零,结果将为正或负无穷大
答案 3 :(得分:1)
您始终可以对* b:
上的溢出进行明确检查long long e = (long long) a * (long long) b;
if (e <= INT_MAX) {
d = e / c;
} else {
d = a * (b / c);
}
当然这仅适用于非负a,b,c。如果它们可能是否定的,您还必须检查INT_MIN。
[更新]您还可以检查a和b中的哪一个更大,因此在除以c时损失的精度更低:
if (a >= b) {
d = a / c * b;
} else {
d = a * (b / c);
}
答案 4 :(得分:1)
对于您所述的问题,我会d = (long long)a * b / c;
当你只需要更多位时,去float
没有任何意义。无需重新安装或投射一切。展开a
足以在表达式中将b
和c
提升为更大的尺寸。
答案 5 :(得分:0)
为什么不使用float
或double
? float
(在intel芯片上)是一个32位浮点数,所以你不一定需要64位进行操作?
答案 6 :(得分:0)
我会按照以下方式做点什么:
if(c){
d = (long long)a * b;
d /= c;
}
else{
// some error code because div by 0 is not allowed
}