C++ pow 异常类型转换 [英] C++ pow unusual type conversion

查看:16
本文介绍了C++ pow 异常类型转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我直接输出 std::pow(10,2) 时,我得到 100 而做 (long)(pow(10,2)) 得到 99.有人可以请解释一下?

When I directly output std::pow(10,2), I get 100 while doing (long)(pow(10,2)) gives 99. Can someone explained this please ?

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

main函数中的代码基本是这样的.

The code is basically this in the main function.

编译器是mingw32-g++.exe -std=c++11 using CodeBlocksWindows 8.1 如果有帮助的话

The compiler is mingw32-g++.exe -std=c++11 using CodeBlocks Windows 8.1 if that helps

推荐答案

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

Floating point numbers are approximations. Occasionally you get a number that can be exactly represented, but don't count on it. 100 should be representable, but in this case it isn't. Something injected an approximation and ruined it for everybody.

从浮点类型转换为整数时,整数不能包含任何小数值,因此它们会被毫不客气地丢弃.没有隐式四舍五入,分数被丢弃.99.9 转换为 99.99 在 99 之后有一百万个 9.

When converting from a floating point type to an integer, the integer cannot hold any fractional values so they are unceremoniously dropped. There is no implicit rounding off, the fraction is discarded. 99.9 converts to 99. 99 with a million 9s after it is 99.

所以在从浮点类型转换为整数之前,先将数字四舍五入,然后再进行转换.除非丢弃分数你想要做的.

So before converting from a floating point type to an integer, round the number, then convert. Unless discarding the fraction is what you want to do.

cout 和大多数输出​​例程,在打印前会礼貌而安静地对浮点值进行舍入,因此如果有一点近似值,用户不会被它打扰.

cout, and most output routines, politely and silently round floating point values before printing, so if there is a bit of an approximation the user isn't bothered with it.

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

This inexactness is also why you shouldn't directly compare floating point values. X probably isn't exactly pi, but it might be close enough for your computations, so you perform the comparison with an epsilon, a fudge factor, to tell if you are close enough.

如果不是using namespace std;,我觉得很有趣,并且花了很多时间试图解决这个问题,甚至不会看到这个问题.

What I find amusing, and burned a lot of time trying to sort out, is would not have even seen this problem if not for using namespace std;.

(long)pow(10,2) 提供 100 的预期结果.(long)std::pow(10,2) 没有.powstd::pow 所采用的路径从 10,2 到 100 的一些差异导致结果略有不同.通过将整个 std 命名空间拉到他们的文件中,OP 不小心把自己踢到了脚上.

(long)pow(10,2) provides the expected result of 100. (long)std::pow(10,2) does not. Some difference in the path from 10,2 to 100 taken by pow and std::pow results in slightly different results. By pulling the entire std namespace into their file, OP accidentally shot themselves in the foot.

这是为什么呢?

在文件的顶部,我们有 using namespace std; 这意味着编译器在查找 时不仅仅考虑 double pow(double, double)>pow 重载,它也可以调用 std::pow 并且 std::pow 是一个漂亮的小模板,确保在使用浮点以外的数据类型调用时并且发生了双倍正确的转换,并且一切都是相同的类型.

Up at the top of the file we have using namespace std; this means the compiler is not just considering double pow(double, double) when looking for pow overloads, it can also call std::pow and std::pow is a nifty little template making sure that when called with datatypes other than float and double the right conversions are taking place and everything is the same type.

(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 时隐含从 intdouble 的转换,我不知道.打电话给语言律师,因为这很微妙.

with an implied conversion from int to double on the call to pow is, I do not know. Call in the language lawyers because it's something subtle.

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

If this is purely a rounding issue then

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

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

should be vulnerable because tempa should be exactly what std::pow returns

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

输出应该是

100
99

我明白了

100
100

所以立即将 std::pow(10, 2) 的返回值转换为 long 不同于存储然后转换.奇怪的.auto tempa 不完全是 std::pow 返回的内容,或者还有其他事情对我来说太深了.

So immediately casting the return of std::pow(10, 2) into a long is different from storing and then casting. Weird. auto tempa is not exactly what std::pow returns or there is something else going on that is too deep for me.

这篇关于C++ pow 异常类型转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆