C ++ Precision使用long long with double

时间:2016-03-02 08:40:33

标签: c++ precision

我正在尝试使用c ++。我写了一个简单的函数,它使用非常大的数字来查找三角形的区域。

我将两个大数字传递给函数,并从一个单独的函数getValue()中返回一个不同方程的单独值。我很好奇为什么当我把1放在括号外的那一行时,就像这样:

return (long long)(a - b / 2.0) + b + 1;

我得到的值9007200509008001

当我将1保留在括号内时,就像这样:

return (long long)(a - b / 2.0 + 1) + b;

我得到9007200509008000

第二个值比第一个值少一个,即使计算应该得到相同的答案。

#include <iostream>

double triangleArea(int b, int h)
{
    long long bh = (long long)b * h;
    return 0.5 * bh;
}

long long getValue()
{
    int deltaY = 18014400;
    int deltaX = 1000000000;

    long b = deltaY + deltaX + 1600;
    double a = triangleArea(deltaX, deltaY);
    return (long long)(a - b / 2.0) + b + 1;
}

int main(int argc, char **argv) 
{
    std::cout << getValue() << std::endl;
}

我确信答案对某些人来说可能是显而易见的,但我无法绕过它。有人可以解释一下吗?

3 个答案:

答案 0 :(得分:6)

当你除以2.0时,你有一个隐含的转换为double。双精度限制为大约15位小数。那么16 th 数字的结果是完美定义的,但可能不是你所期望的。

如果您需要准确性,请尝试使用long longunsigned long long并谨慎控制您没有溢出。如果还不够,则必须使用多精度算术(例如GMP)。因为只要使用双浮点,就可以将精度限制为53位二进制数,或者大约15-16位十进制数。

答案 1 :(得分:0)

问题是你的师和变量a的隐式转换加倍。

请查看以下样本以获取许可:

#include <iostream>

double triangleArea(int b, int h)
{
    long long bh = (long long)b * h;
    return 0.5 * bh;
}

long long getValue()
{
    int deltaY = 18014400;
    int deltaX = 1000000000;

    long b = deltaY + deltaX + 1600;
    double a = triangleArea(deltaX, deltaY);

    long long c = b / 2.0;

    long long d1 = a - c;
    long long d2 = ((long long)a) - c + 1;

    long long e1 = d1 + b + 1;
    long long e2 = d2 + b;

    return e1;
}

int main(int argc, char **argv)
{
    std::cout << getValue() << std::endl;
}

long long的明确演员正在那里解决你的特殊问题。

请注意您的变量准确性并在它们之间进行转换。

答案 2 :(得分:-1)

long long通常具有double的更高精度。例如,如果两者都是64位,则long long具有64位的精度,但double仅具有53位精度(52位尾数,隐含msb = 1)。

在您的情况下,这意味着a - b / 2.0 + 1double的{​​{1}}常量相同,但a - b / 2.0(long long)(a - b / 2.0) + b + 1常量不同long long