以下两段代码产生两种不同的输出。
//this one gives incorrect output
cpp_dec_float_50 x=log(2)
std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits)<< x << std::endl;
它给出的输出是
0.69314718055994528622676398299518041312694549560547
只能在小数点后15位正确。如果x是双倍的话,即便如此,我们也会得到前15位正确的数字。似乎结果溢出了。我不知道为什么它应该。 cpp_dec_float_50应该具有50位精度。
//this one gives correct output
cpp_dec_float_50 x=2
std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits)<< log(x) << std::endl;
它给出的输出是
根据wolframaplha,这是正确的。0.69314718055994530941723212145817656807550013436026
答案 0 :(得分:5)
当你执行log(2)
时,你在标准库中使用log
的实现,它接受一个double并返回一个double,因此执行计算的精度加倍。
只有在计算完之后(如你所指出的那样,只有15位数的精度)才会将结果转换为50位数的扩展精度数。
当你这样做时:
cpp_dec_float_50 x=2;
/* ... */ log(x);
您正在传递一个扩展的精度数字,因此(显然)正在选择log
的扩展精度重载,因此它会将结果计算为您(显然)想要的50位精度。 / p>
答案 1 :(得分:3)
这实际上只是一个复杂的版本:
float a = 1 / 2;
这里,1 / 2
是整数除法,因为参数是整数。在计算结果后,它只会转换为float
以存储在a
中。
如何计算结果的C ++规则不依赖于您对该结果的处理方式。因此,无论您将其存储在log(2)
,int
还是float
中,cpp_dec_float_50
的实际计算都是相同的。
你的第二段代码相当于:
float b = 1;
float c = 2;
float a = b / c;
现在,您在/
上调用了float
,因此您获得了浮点除法。 C ++的规则做考虑了参数和参数的类型。这很复杂,并且试图考虑你对结果所做的事情会使C ++已经过于复杂的规则对于凡人来说是不可理解的。