如何获得最准确的结果?

时间:2009-05-15 03:27:23

标签: c

假设:

unsigned int a, b, c, d;

我想:

d = a * b / c;

和(a * b)可能溢出; (b / c)也可能等于零并且准确度较低。

使用64位的演员可能会让事情发挥作用,但我想知道在d中获得最准确结果的最佳方法。

有什么好的解决方案吗?

7 个答案:

答案 0 :(得分:5)

我要么:

  • 如果适用于a,b和c的范围,则转换为64位。
  • 使用像GMP
  • 这样的无限精度库
  • 如果您发现这些结果可以接受,则转为floatdouble并返回。

答案 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足以在表达式中将bc提升为更大的尺寸。

答案 5 :(得分:0)

为什么不使用floatdoublefloat(在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
}
相关问题