简体   繁体   English

C ++ Precision使用long long with double

[英]C++ Precision using long long with double

I am experimenting with c++. 我正在尝试使用c ++。 I wrote a simple function that finds the area of a triangle using very large numbers. 我写了一个简单的函数,它使用非常大的数字来查找三角形的区域。

I pass two large numbers into the function, and from a separate function, getValue() I return a separate value from a different equation. 我将两个大数字传递给函数,并从一个单独的函数getValue()我从一个不同的方程返回一个单独的值。 I'm curious why when I place the 1 on the line outside the parenthesis, like so: 我很好奇为什么当我把1放在括号外的那一行时,如下:

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

I get the value 9007200509008001 我得到的值9007200509008001

And when I keep the 1 inside the parenthesis, like so: 当我将1保留在括号内时,如下所示:

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

I get 9007200509008000 我得到9007200509008000

The second value is one less than the first, even though the computation should result in equal answers. 第二个值比第一个值小1,即使计算应该得到相同的答案。

#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;
}

I'm sure the answer is probably obvious to some people, but I can't wrap my head around it. 我确定答案对某些人来说可能是显而易见的,但我无法绕过它。 Can someone explain? 谁能解释一下?

When you divide by 2.0 you have an implicit conversion to double. 除以2.0时,您将隐式转换为double。 Double accuracy is limited to about 15 decimal digits. 双精度限制为大约15位小数。 So what happens to the 16 th digit is perfectly defined, but may not be what you expect. 那么第16 位的数字是完美定义的,但可能不是你所期望的。

If you need accuracy, try to use long long or unsigned long long and carefully control that you have no overflow. 如果您需要准确性,请尝试使用long longunsigned long long并小心控制您没有溢出。 If it is not enough, you will have to use multi-precision arithmetic (for example GMP ). 如果还不够,则必须使用多精度算法(例如GMP )。 Because as soon as you use double floating points, you are limited to 53 binary digits of accuracy, or about 15-16 decimal digits. 因为只要使用双浮点,就可以将精度限制为53位二进制数,或大约15-16位十进制数。

The problem is an implicit cast to double at your division and the variable a . 问题是你的师和变量a的隐式转换加倍。

Check out the following sample for clearance: 查看以下样本以获得许可:

#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;
}

The explicit cast to long long is solving your special problem there. long long的明确演员是在那里解决你的特殊问题。

Be aware of your variable accuracy and converting between them. 注意您的变量准确性并在它们之间进行转换。

long long typically has a higher precision that double . long long通常具有更高的精度, double For instance, if both are 64 bits, then long long has a precision of 64 bits, but double has only 53-bit precision (a 52-bit mantissa with implied msb=1). 例如,如果两者都是64位,则long long具有64位的精度,但是double仅具有53位精度(52位尾数,隐含msb = 1)。

In your case, what this means is that a - b / 2.0 + 1 is the same double constant as a - b / 2.0 , but (long long)(a - b / 2.0) + b + 1 is not the same long long constant as (long long)(a - b / 2.0) + b . 你的情况,这是什么意思是a - b / 2.0 + 1是相同的double常数作为a - b / 2.0 ,但(long long)(a - b / 2.0) + b + 1是不一样的long long常数为(long long)(a - b / 2.0) + b

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM