C++ pow异常类型转换
C++ pow unusual type conversion
当我直接输出std::pow(10,2)时,我在做(long)(pow(10,2))时得到100得到99。有人可以解释一下吗?
cout<<pow(10,2)<<endl;
cout<<(long)(pow(10,2))<<endl;
main函数中的代码基本就是这样
编译器是 mingw32-g++.exe -std=c++11 使用 CodeBlocks
Windows 8.1 如果有帮助
浮点数是近似值。偶尔你会得到一个可以精确表示的数字,但不要指望它。 100 应该是可表示的,但在本例中不是。有些东西注入了一个近似值并为大家毁了它。
当从浮点类型转换为整数时,整数不能包含任何小数值,所以它们被毫不客气地丢弃了。没有隐式四舍五入,分数被丢弃。 99.9 转换为 99. 99 在 99 之后加上一百万个 9。
所以在从浮点类型转换为整数之前,先将数字四舍五入,然后再转换。除非丢弃分数 是 你想要做的。
cout
和大多数输出例程,在打印前礼貌而安静地舍入浮点值,因此如果有一点近似值,用户不会为它烦恼。
这种不精确性也是您不应直接比较浮点值的原因。 X 可能不完全是 pi,但对于您的计算来说它可能足够接近,因此您使用 epsilon(一个软糖因子)进行比较,以判断您是否足够接近。
我觉得很有趣,并且花了很多时间试图解决这个问题,如果不是 using namespace std;
,我什至不会看到这个问题。
(long)pow(10,2)
提供了预期结果 100。(long)std::pow(10,2)
没有。 pow
和 std::pow
所采用的从 10,2 到 100 的路径存在一些差异,导致结果略有不同。通过将整个 std
命名空间拉入他们的文件,OP 不小心搬起石头砸了自己的脚。
这是为什么?
在文件的顶部我们有 using namespace std;
这意味着编译器在查找 pow
重载时不仅仅考虑 double pow(double, double)
,它还可以调用 std::pow
和 std::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)
在对 pow
的调用中从 int
到 double
的隐式转换,我不知道。打电话给语言律师,因为这很微妙。
如果这纯粹是一个舍入问题,那么
auto tempa = std::pow(10, 2);
应该容易受到攻击,因为 tempa 应该正是 std::pow
returns
cout << tempa << endl;
cout << (long) tempa << endl;
输出应该是
100
99
我明白了
100
100
所以立即将 std::pow(10, 2)
的 return 转换为 long
不同于存储然后转换。诡异的。 auto tempa
不完全是 std::pow
return 的意思,或者还有其他事情对我来说太深了。
这些是 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 运行-time 不喜欢它的方式。我假设 windows 看到的是 99.9999 之类的东西,当它被转换为整数类型时,它会发言。
int a = 3/2; // a is = 1
mingw uses the Microsoft C run-time libraries and their implementation of printf does not support the 'long double' type. As a work-around, you could cast to 'double' and pass that to printf instead.
Therefore, you need double double:
On the x86 architecture, most C compilers implement long double as the 80-bit extended precision type supported by x86 hardware (sometimes stored as 12 or 16 bytes to maintain data structure alignment), as specified in the C99 / C11 standards (IEC 60559 floating-point arithmetic (Annex F)). An exception is Microsoft Visual C++ for x86, which makes long double a synonym for double.[2] The Intel C++ compiler on Microsoft Windows supports extended precision, but requires the /Qlong‑double switch for long double to correspond to the hardware's extended precision format.[3]
cout<<pow(10,2)<<endl;
cout<<(long)(pow(10,2))<<endl;
main函数中的代码基本就是这样
编译器是 mingw32-g++.exe -std=c++11 使用 CodeBlocks Windows 8.1 如果有帮助
浮点数是近似值。偶尔你会得到一个可以精确表示的数字,但不要指望它。 100 应该是可表示的,但在本例中不是。有些东西注入了一个近似值并为大家毁了它。
当从浮点类型转换为整数时,整数不能包含任何小数值,所以它们被毫不客气地丢弃了。没有隐式四舍五入,分数被丢弃。 99.9 转换为 99. 99 在 99 之后加上一百万个 9。
所以在从浮点类型转换为整数之前,先将数字四舍五入,然后再转换。除非丢弃分数 是 你想要做的。
cout
和大多数输出例程,在打印前礼貌而安静地舍入浮点值,因此如果有一点近似值,用户不会为它烦恼。
这种不精确性也是您不应直接比较浮点值的原因。 X 可能不完全是 pi,但对于您的计算来说它可能足够接近,因此您使用 epsilon(一个软糖因子)进行比较,以判断您是否足够接近。
我觉得很有趣,并且花了很多时间试图解决这个问题,如果不是 using namespace std;
,我什至不会看到这个问题。
(long)pow(10,2)
提供了预期结果 100。(long)std::pow(10,2)
没有。 pow
和 std::pow
所采用的从 10,2 到 100 的路径存在一些差异,导致结果略有不同。通过将整个 std
命名空间拉入他们的文件,OP 不小心搬起石头砸了自己的脚。
这是为什么?
在文件的顶部我们有 using namespace std;
这意味着编译器在查找 pow
重载时不仅仅考虑 double pow(double, double)
,它还可以调用 std::pow
和 std::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)
在对 pow
的调用中从 int
到 double
的隐式转换,我不知道。打电话给语言律师,因为这很微妙。
如果这纯粹是一个舍入问题,那么
auto tempa = std::pow(10, 2);
应该容易受到攻击,因为 tempa 应该正是 std::pow
returns
cout << tempa << endl;
cout << (long) tempa << endl;
输出应该是
100
99
我明白了
100
100
所以立即将 std::pow(10, 2)
的 return 转换为 long
不同于存储然后转换。诡异的。 auto tempa
不完全是 std::pow
return 的意思,或者还有其他事情对我来说太深了。
这些是 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 运行-time 不喜欢它的方式。我假设 windows 看到的是 99.9999 之类的东西,当它被转换为整数类型时,它会发言。
int a = 3/2; // a is = 1
mingw uses the Microsoft C run-time libraries and their implementation of printf does not support the 'long double' type. As a work-around, you could cast to 'double' and pass that to printf instead. Therefore, you need double double:
On the x86 architecture, most C compilers implement long double as the 80-bit extended precision type supported by x86 hardware (sometimes stored as 12 or 16 bytes to maintain data structure alignment), as specified in the C99 / C11 standards (IEC 60559 floating-point arithmetic (Annex F)). An exception is Microsoft Visual C++ for x86, which makes long double a synonym for double.[2] The Intel C++ compiler on Microsoft Windows supports extended precision, but requires the /Qlong‑double switch for long double to correspond to the hardware's extended precision format.[3]