C ++ pow异常类型转换

时间:2015-10-17 14:54:59

标签: c++ type-conversion pow

enter image description here当我直接输出std :: pow(10,2)时,我得到100(做长)(pow(10,2))得到99.有人可以解释一下吗?

cout<<pow(10,2)<<endl;
cout<<(long)(pow(10,2))<<endl;

代码基本上是在主函数中。

使用CodeBlocks编译器是mingw32-g ++。exe -std = c ++ 11 Windows 8.1如果有帮助

2 个答案:

答案 0 :(得分:2)

浮点数是近似值。偶尔你会得到一个可以准确表示的数字,但不要指望它。 100应该是可表示的,但在这种情况下它不是。有些东西注入了近似值,并为每个人毁了它。

当从浮点类型转换为整数时,整数不能保存任何小数值,因此会毫不客气地删除它们。没有隐式舍入,分数被丢弃。 99.9在99之后转换为99. 99,有9百万9。

因此,在从浮点类型转换为整数之前,将数字四舍五入,然后转换。除非丢弃分数 你想做什么。

cout和大多数输出​​例程,在打印之前礼貌地和静默地舍入浮点值,所以如果有一点近似值,用户就不会对它感到困扰。

这种不精确性也是您不应直接比较浮点值的原因。 X可能不完全是pi,但它可能足够接近您的计算,因此您可以使用epsilon(一个软糖因子)进行比较,以判断您是否足够接近。

我觉得有趣,并且花了很多时间试图理清,如果不是using namespace std;,就不会看到这个问题。

(long)pow(10,2)提供100的预期结果。(long)std::pow(10,2)没有。 powstd::pow采用的路径从10,2到100之间存在一些差异会导致略有不同的结果。通过将整个std命名空间拉入其文件中,OP意外地将自己射入了脚中。

为什么?

在文件的顶部我们有using namespace std;这意味着编译器在查找double pow(double, double)重载时不仅仅考虑pow,还可以调用std::powstd::pow是一个漂亮的小模板,确保在使用除float和double之外的数据类型进行调用时,正在进行正确的转换并且所有内容都是相同的类型。

(long)(pow(10,2))

不匹配

double pow(double, double)

以及它与

的模板实例化相匹配
double std::pow(int, int)

哪个,我可以告诉解析到

附近
return pow(double(10), double(2));
经过一些模板伏都教之后。

之间有什么区别
pow(double(10), double(2))

pow(10, 2)
int的调用中隐含从doublepow的转换是

,我不知道。打电话给语言律师,因为这是微妙的。

如果这纯粹是一个舍入问题,那么

auto tempa = std::pow(10, 2);

应该是易受攻击的,因为tempa应该正是std::pow返回的

cout << tempa << endl; 
cout << (long) tempa << endl; 

,输出应为

100
99

我得到了

100
100

因此,立即将std::pow(10, 2)的回复转换为long与存储然后转换不同。奇怪的。 auto tempa并不完全是std::pow返回的内容,或者其他内容对我来说太深了。

答案 1 :(得分:0)

这些是std :: pow重载:

float       pow( float base, float exp );

double      pow( double base, double exp );

long double pow( long double base, long double exp );

float       pow( float base, int iexp );//(until C++11)

double      pow( double base, int iexp );//(until C++11)

long double pow( long double base, int iexp ); //(until C++11)

Promoted    pow( Arithmetic1 base, Arithmetic2 exp ); //(since C++11)

但是你的奇怪行为是MINGW关于双重存储的奇怪之处以及Windows运行时如何不喜欢它。我假设Windows看到的是99.9999这样的东西,当它被转换为整体类型时,它会占据一席之地。

int a = 3/2; // a is = 1
  

mingw使用Microsoft C运行时库,它们的printf实现不支持'long double'类型。作为解决方法,你可以强制转换为'double'并将其传递给printf。   因此,您需要双倍双倍:

     

在x86架构上,大多数C编译器实现long double作为x86硬件支持的80位扩展精度类型(有时存储为12或16字节以保持数据结构对齐),如C99 / C11标准中所规定的( IEC 60559浮点运算(附件F))。一个例外是用于x86的Microsoft Visual C ++,它使long double成为double的同义词。[2] Microsoft Windows上的英特尔C ++编译器支持扩展精度,但需要/ Qlong-double开关用于long double,以对应硬件的扩展精度格式。[3]