【问题标题】:Multiplying floats and keep/get double precision accuracy乘以浮点数并保持/获得双精度精度
【发布时间】:2017-01-19 01:39:26
【问题描述】:

我有一个带浮点数的函数,我正在用它们进行一些计算,并且我希望在返回的结果中保持尽可能高的准确性。我读到,当您将两个浮点数相乘时,有效数字的数量就会增加一倍。

所以当两个浮点数相乘时,例如float e, f; 和我做double g = e * f,这些位什么时候会被截断?

在下面的示例函数中,我是否需要强制转换,如果需要,在哪里?这是一个紧密的内部循环,如果我将 static_cast<double>(x) 放在每个变量 a b c d 周围使用它,我会减速 5-10%。但我怀疑我不需要单独转换每个变量,并且只在某些位置,如果有的话?或者在这里返回一个双精度并没有给我任何好处,我也可以只返回一个浮点数?

double func(float a, float b, float c, float d) {
    return (a - b) * c + (a - c) * b;
}

【问题讨论】:

  • 您只需要一个转换,因为其他操作数将为您转换“如果任一操作数是双精度,另一个操作数将转换为双精度” 来源:en.cppreference.com/w/cpp/language/… 但是这仍然会给你同样的减速。关于返回双精度的第二个问题取决于您如何处理返回的结果。
  • 是的,但就我而言,两个(所有)操作数(返回类型除外)都是浮点数?
  • 如果您在任何地方使用double,您可能会获得更好的性能(以及更好的准确性)。这样可以节省转换开销。
  • @5gon12eder - “如果你在任何地方都使用 double,可以获得更好的性能(以及更好的准确性)”......不要忘记:“以 RAM 消耗为代价”的价格标签

标签: c++ casting floating-point precision


【解决方案1】:

意义比 5-10% 的减速更重要。我会做什么:

double func_impl(double a, double b, double c, double d) {
    return (a - b) * c + (a - c) * b;
}

double func(float a, float b, float c, float d) {
    return func_impl(a, b, c, d);
}

即使它有点慢,我也会选择它,因为它表达了您希望在计算中很好地实现双精度并且只需要界面上的浮点数的想法;同时它使您的函数体与强制转换分开(后者是一步完成的)。

【讨论】:

    【解决方案2】:

    当您将两个浮点数相乘而不进行强制转换时,结果会以浮点精度(即截断)计算,然后转换为双精度。

    要以双精度计算结果,您需要先将至少一个操作数转换为双精度。然后整个计算将以双精度完成(所有浮点值都将被转换)。但是,这将造成同样的放缓。放缓可能是因为将数字从浮点数转换为双精度数并非完全无关紧要(不同的位大小以及指数和尾数的范围)。

    如果我这样做并控制函数定义,我会将所有参数作为双精度传递(我通常在任何地方都使用双精度,在现代计算机上,浮点计算与双精度计算之间的速度差异可以忽略不计,只有问题可能是对大型值数组进行操作时的内存吞吐量和缓存性能)。

    顺便说一句。对精度重要的情况实际上不是乘法,而是加法/减法——这就是精度可以产生很大影响的地方。考虑加/减 1e+6 和 1e-3。

    【讨论】:

    • 谢谢你,你的前三句话完美地回答了我的问题!其他信息也非常有用。
    猜你喜欢
    • 1970-01-01
    • 2018-02-23
    • 2018-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    相关资源
    最近更新 更多