为什么我在这里得到两个不同的输出?

时间:2013-04-13 05:41:44

标签: c++ boost floating-point

以下两段代码产生两种不同的输出。

//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;

它给出的输出是

  

0.69314718055994530941723212145817656807550013436026

根据wolframaplha,这是正确的。

2 个答案:

答案 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 ++已经过于复杂的规则对于凡人来说是不可理解的。