C ++或C中浮点乘法的最佳实践?

时间:2016-11-14 09:39:56

标签: c precision multiplication floating-accuracy

我需要执行400 * 256.3的简单乘法。结果是102520.直线前进,简单。但是在C ++(或C)中实现这种乘法对我来说有点棘手和困惑。

我知道浮点数没有表示在计算机中。我写了代码来说明情况。输出也附加了。

所以,如果我使用float类型变量进行乘法运算,我会遇到舍入误差。使用double类型变量可以避免这个问题。但是,让我说我在嵌入式系统上的资源非常有限,我必须尽可能地优化变量类型,如何使用float类型变量执行乘法而不易受舍入误差的影响? / p>

我知道计算机完成的浮点运算并没有被打破。但我很好奇进行浮点数学的最佳实践。 256.3只是一个插图的值。我不知道在运行时我会得到什么浮点值。但这肯定是一个浮点值。

int main()
{
    //perform 400 * 256.3
    //result should be 102520

    float floatResult = 0.00f;
    int intResult = 0;
    double doubleResult = 0.00;

    //float = int * float
    floatResult = 400 * 256.3f;
    printf("400 * 256.3f = (float)->%f\n", floatResult);

    //float = float * float
    floatResult = 400.00f * 256.3f;
    printf("400.00f * 256.3f = (float)->%f\n", floatResult);

    printf("\n");

    //int = int * float
    intResult = 400 * 256.3f;
    printf("400 * 256.3f = (int)->%d\n", intResult);

    //int = float * float;
    intResult = 400.00f * 256.3f;
    printf("400.00f * 256.3f = (int)->%d\n", intResult);

    printf("\n");

    //double = double * double
    doubleResult = 400.00 * 256.3;
    printf("400.00 * 256.3 = (double)->%f\n", doubleResult);

    //int = double * double;
    intResult = 400.00 * 256.3;
    printf("400.00 * 256.3 = (int)->%d\n", intResult);

    printf("\n");

    //double = int * double
    doubleResult = 400 * 256.3;
    printf("400 * 256.3 = (double)->%f\n", doubleResult);

    //int = int * double
    intResult = 400 * 256.3;
    printf("400 * 256.3 = (int)->%d\n", intResult);

    printf("\n");

    //will double give me rounding error?
    if (((400.00 * 256.3) - 102520) != 0) {
        printf("Double give me rounding error!\n");
    }

    //will float give me rounding error?
    if (((400.00f * 256.3f) - 102520) != 0) {
        printf("Float give me rounding error!\n");
    }

    return 0;
}

Output from the code above

3 个答案:

答案 0 :(得分:5)

如果您有一个固定的小数位数(256.3的情况下为1)以及结果的有界范围,您可以使用整数乘法,并调整十进制数字到整数的移位除法:

int result = (400 * 2563) / 10;

舍入误差是浮点算术所固有的,除了少数几个可以精确表示所有操作数的情况。无论您选择float还是double,只会在发生错误时影响,而不是 if

答案 1 :(得分:2)

首先,要了解类型double与类型float存在的问题完全相同。两种类型都没有无限精度,因此这两种类型都容易受到精度损失和其他问题的影响。

关于你能做什么:根据你正在做的事情以及许多克服它们的技巧,出现了许多不同的问题。关于这些技术已经写了很多很多的词;我建议做一个关于“避免浮点错误”的网络搜索。但基本要点是:

  • 知道浮点结果永远不会精确
  • 不要尝试比较浮点数以获得完全相等
  • 比较浮点数是否相等时,请使用适当的“epsilon”范围
  • 经过计算,通常可以将最终值明确地舍入到所需的精度(特别是在打印出来时)
  • 谨防每一步都会导致精度损失增加的算法

另见https://www.eskimo.com/~scs/cclass/handouts/sciprog.html

答案 2 :(得分:1)

显示问题的一个关键弱点是转换为int intResult。发布的问题是乘以比较,但代码仅显示围绕int转换的问题。

如果代码需要将FP值转换为最近的整数,请使用rint()round()nearbyint()lround(),而不是整数赋值。