代码之家  ›  专栏  ›  技术社区  ›  Sam Liao

我怎样才能得到最准确的结果?

c
  •  0
  • Sam Liao  · 技术社区  · 15 年前

    鉴于:

    unsigned int a, b, c, d;
    

    我想要:

    d = a * b / c;
    

    _¼_a*b)可能溢出;另外(b/c)可能等于零,并且精度较低。

    也许64位的强制转换可以使事情正常工作,但我想知道在D中获得最精确结果的最佳方法。

    有什么好的解决办法吗?

    7 回复  |  直到 15 年前
        1
  •  1
  •   dwc    15 年前

    对于你的问题,如前所述,我会的。 d = (long long)a * b / c;

    去没有意义 float 当你只需要更多的比特。无需重新申报或铸造一切。铸造 a 足以提升 b c 使表达式中的大小更大。

        2
  •  5
  •   Matt J Jørgen Fogh    15 年前

    我也可以:

    • 强制转换为64位,如果这适用于A、B和C的范围。
    • 使用无限精度库 GMP
    • 铸造成 float double 回到过去,如果你觉得这些结果可以接受的话。
        3
  •  3
  •   Laurence Gonsalves    15 年前

    为了获得最佳的精度,你需要在除法之前进行乘法运算。正如您所暗示的,您将希望使用比int多两倍的位:

    int64_t d = (int64_t) a * (int64_t) b;
    d /= c;
    

    你不需要这两种类型,但可以说它们会让你更清楚一点。

    注意,如果c足够小,那么d仍然可以大于int,这对你来说可能是个问题,也可能不是问题。如果你确定不是这样的话,你可以在最后把它降为int。

        4
  •  1
  •   TStamper    15 年前

    在浮点运算中使用float或double, 允许被零除 ,结果将是正无穷大或负无穷大

        5
  •  1
  •   Nathan Kitchen    15 年前

    您始终可以对a*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);
    }
    
        6
  •  0
  •   poundifdef    15 年前

    为什么不使用 float double ?一 浮动 (在英特尔芯片上)是一个32位的浮点数,所以您不一定需要64位来进行操作吗?

        7
  •  0
  •   warren    15 年前

    我会按照以下几点做一些事情:

    if(c){
        d = (long long)a * b;
        d /= c;
    }
    else{
        // some error code because div by 0 is not allowed
    }