我正在尝试使用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;
}
我确信答案对某些人来说可能是显而易见的,但我无法绕过它。有人可以解释一下吗?
答案 0 :(得分:6)
当你除以2.0
时,你有一个隐含的转换为double。双精度限制为大约15位小数。那么16 th 数字的结果是完美定义的,但可能不是你所期望的。
如果您需要准确性,请尝试使用long long
或unsigned 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 + 1
与double
的{{1}}常量相同,但a - b / 2.0
与(long long)(a - b / 2.0) + b + 1
常量不同long long
。