在线计算或两行之间的区别
这是我在C ++中的代码。我正在使用GCC版本11.2.0的G ++ -11。
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
int main()
{
string t="90071992547409929007199254740993";
//separateNumbers(t);
unsigned long long stringNum=0;
for (int j=16;j<32;j++)
{
stringNum += (t[j]-'0')*pow(10,32-j-1);
}
cout << stringNum;
return 0;
}
我希望将最后16位数字作为数字获得的简单代码提供9929007199254740992,而不是9929007199254740993。
但是,代码的更改
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
int main()
{
string t="90071992547409929007199254740993";
//separateNumbers(t);
unsigned long long stringNum=0;
for (int j=16;j<32;j++)
{
unsigned long long temp = (t[j]-'0')*pow(10,32-j-1);
stringNum += temp;
}
cout << stringNum;
return 0;
}
给出了所需的结果,90077199254740993。我们如何解释两个代码之间的区别?
Here is my code in C++. I'm using g++-11 with gcc version 11.2.0.
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
int main()
{
string t="90071992547409929007199254740993";
//separateNumbers(t);
unsigned long long stringNum=0;
for (int j=16;j<32;j++)
{
stringNum += (t[j]-'0')*pow(10,32-j-1);
}
cout << stringNum;
return 0;
}
This simple code, which I expected to get the last 16 digits as a number, gives 9929007199254740992, not 9929007199254740993.
However, the change of code
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
int main()
{
string t="90071992547409929007199254740993";
//separateNumbers(t);
unsigned long long stringNum=0;
for (int j=16;j<32;j++)
{
unsigned long long temp = (t[j]-'0')*pow(10,32-j-1);
stringNum += temp;
}
cout << stringNum;
return 0;
}
gives the desired result, 9007199254740993. How can we explain such a difference between two codes?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如区别在于将浮点算术与整数混合在一起。
对于感兴趣的人来说,更多信息:
差异在您的循环的最后一次迭代中表现出来。
在第一种情况中,您有:
等效于:
pow
返回double
,因此Expresion(t [j [J ] - '0')*POW(10,32-J-1)
将为double
以及:stringnum +(t [j] - ' - ' 0')*POW(10,32-J-1)
。您期望的值(9007199254740993)无法用
double
表示。最接近的值是:9007199254740992。当将其分配回IntegerStringnum
时,它一直保持 9007199254740992 。您可以在此处看到有关此问题的更多信息:浮点数学损坏了?。
如果尝试以下行,您还可以轻松地看到这一点(您的编译器还将给出警告关于可能丢失精度的):
哪个打印:
9007199254740992
。在第二种情况下您将最后一个数字的值分配给
temp
:(t [j] - '0')*POW(10,32-J -1)
是double
带值3,可以在double
中表现出来。然后将其分配到整数temp
,也是3。执行时:
使用整数算术并获得正确的结果: 9007199254740993 。
As mentioned in @PaulMcKenzie's comment, the source of the difference is mixing floating-point arithmetics with integers.
Some more info for those who are interested:
The difference manifests in the last iteration of your loop.
In the first case, you have:
which is equivalent to:
pow
returns adouble
, and so the expresion(t[j]-'0')*pow(10,32-j-1)
will be of typedouble
, as well as:stringNum + (t[j]-'0')*pow(10,32-j-1)
.The value you expect (9007199254740993) cannot be represented in a
double
. The closest value is: 9007199254740992. When assigned back to integerstringNum
it stays 9007199254740992.You can see more about this issue here: Is floating point math broken?.
You can also see this easily if you try the following lines (your compiler will also give a warning about the possible loss of precision):
Which prints:
9007199254740992
.In the second case you assign the value for the last digit to
temp
:(t[j]-'0')*pow(10,32-j-1)
is adouble
with value 3, which incidently can be represented in adouble
. Then it gets assigned into an integertemp
which is also 3.When you execute:
You use integer arithmetic and get the correct result: 9007199254740993.