g++和vc6.0环境下 几种常见数据类型的最大范围问题
2015-04-23 12:59
344 查看
g++环境中:
int 占4个字节,也就是32位所以有符号int 的最大值是2^31-1=2147483647
无符号int 的最大值是2^32-1=4294967295
unsigned == unsigned int #include<iostream> #include<cmath> using namespace std; int main(){ //cout<<sizeof(unsigned)<<endl; int i = pow(2,31)-1 ; cout<<"2^31-1="i<<endl; unsigned int ui = pow(2,32)-1 ; cout<<"2^32-1="ui<<endl; return 0; }
经过测试发现在g++中,int64 == long == long long,都是占8个字节
8个字节,共8*8=64位,所以按理来说对于
有符号long 最大值应该是2^63-1=9223372036854775807
无符号long 最大值应该是2^64-1=18446744073709551615
但是写到代码里却发现有问题啊
#include<iostream> #include<cmath> using namespace std; int main(){ for(unsigned i =30;i<65;i++) { unsigned long r = pow(2,i)-1 ; cout<<"2 ^ "<<i<<" = "<<r<<endl; } return 0; }输出:
2 ^ 44 = 17592186044415 2 ^ 45 = 35184372088831 2 ^ 46 = 70368744177663 2 ^ 47 = 140737488355327 2 ^ 48 = 281474976710655 2 ^ 49 = 562949953421311 2 ^ 50 = 1125899906842623 2 ^ 51 = 2251799813685247 2 ^ 52 = 4503599627370495 2 ^ 53 = 9007199254740991 2 ^ 54 = 18014398509481984 2 ^ 55 = 36028797018963968 2 ^ 56 = 72057594037927936 2 ^ 57 = 144115188075855872 2 ^ 58 = 288230376151711744 2 ^ 59 = 576460752303423488 2 ^ 60 = 1152921504606846976 2 ^ 61 = 2305843009213693952 2 ^ 62 = 4611686018427387904 2 ^ 63 = 9223372036854775808 2 ^ 64 = 0可以看出unsigned long的最大值是2^63=9223372036854775808
而且注意我们输出的结果是pow(2,i)-1,所以按理最后的结果一定是一个奇数,但是从i=54以后明显数据就不对了!这是为什么?!
下面在用有符号的long 试试:
#include<iostream> #include<cmath> #include<cstdio> using namespace std; int main(){ for(unsigned i =30;i<65;i++) { long r = pow(2,i)-1 ; cout<<"2 ^ "<<i<<" = "<<r<<endl; } return 0; }输出的结果是这样的:
2 ^ 45 = 35184372088831 2 ^ 46 = 70368744177663 2 ^ 47 = 140737488355327 2 ^ 48 = 281474976710655 2 ^ 49 = 562949953421311 2 ^ 50 = 1125899906842623 2 ^ 51 = 2251799813685247 2 ^ 52 = 4503599627370495 2 ^ 53 = 9007199254740991 2 ^ 54 = 18014398509481984 2 ^ 55 = 36028797018963968 2 ^ 56 = 72057594037927936 2 ^ 57 = 144115188075855872 2 ^ 58 = 288230376151711744 2 ^ 59 = 576460752303423488 2 ^ 60 = 1152921504606846976 2 ^ 61 = 2305843009213693952 2 ^ 62 = 4611686018427387904 2 ^ 63 = -9223372036854775808 2 ^ 64 = -9223372036854775808
可以看出:按理应该可以正确表示出2^63-1的但是结果貌似导致了符号位溢出,而且最后真正正确的结果也只是截止到i=54!
对于ACMer常用的long long 类型,结果也是一样的 !不信大家可以试一下。
然后是在vc6.0环境下:
#include<iostream> #include<cmath> using namespace std; int main(){ //cout<<sizeof(unsigned)<<endl; int i = pow(2,31)-1 ; cout<<"2^31-1="<<i<<endl; unsigned int ui = pow(2,32)-1 ; cout<<"2^32-1="<<ui<<endl; return 0; }
结果正确。
在vc6.0环境下,并没有long long数据类型,使用long long 会报错。
在vc6.0中,long = int 都是占4字节,可以表示32位2进制数。
并且,在vc6.0中,long long = __int64占用8字节,可以表示64位2进制数。
现在看看__int64可以表示的最大数:
#include<iostream> #include<cmath> using namespace std; int main(){ for(int i=30;i<65;i++) { __int64 r = pow(2,i)-1; //cout<<"2 ^ "<<i<<"="<<r<<endl; //使用cout输出__int64会报错! printf("2 ^ %d = %I64d\n",i,r); } return 0; }输出结果:
2 ^ 45 = 35184372088831 2 ^ 46 = 70368744177663 2 ^ 47 = 140737488355327 2 ^ 48 = 281474976710655 2 ^ 49 = 562949953421311 2 ^ 50 = 1125899906842623 2 ^ 51 = 2251799813685247 2 ^ 52 = 4503599627370495 2 ^ 53 = 9007199254740991 2 ^ 54 = 18014398509481984 2 ^ 55 = 36028797018963968 2 ^ 56 = 72057594037927936 2 ^ 57 = 144115188075855872 2 ^ 58 = 288230376151711744 2 ^ 59 = 576460752303423488 2 ^ 60 = 1152921504606846976 2 ^ 61 = 2305843009213693952 2 ^ 62 = 4611686018427387904 2 ^ 63 = -9223372036854775808 2 ^ 64 = -9223372036854775808可以看出有符号的__int64,在i=63的时候发生符号溢出,并且在i=54以后结果都出现了误差!出现的结果和g++环境中是一样的。
下面是无符号的__int64的输出情况:
#include<iostream> #include<cmath> using namespace std; int main(){ for(int i=30;i<65;i++) { unsigned __int64 r = pow(2,i)-1; //cout<<"2 ^ "<<i<<"="<<r<<endl; //使用cout输出__int64会报错! printf("2 ^ %d = %I64u\n",i,r); } return 0; }输出结果:
2 ^ 45 = 35184372088831 2 ^ 46 = 70368744177663 2 ^ 47 = 140737488355327 2 ^ 48 = 281474976710655 2 ^ 49 = 562949953421311 2 ^ 50 = 1125899906842623 2 ^ 51 = 2251799813685247 2 ^ 52 = 4503599627370495 2 ^ 53 = 9007199254740991 2 ^ 54 = 18014398509481984 2 ^ 55 = 36028797018963968 2 ^ 56 = 72057594037927936 2 ^ 57 = 144115188075855872 2 ^ 58 = 288230376151711744 2 ^ 59 = 576460752303423488 2 ^ 60 = 1152921504606846976 2 ^ 61 = 2305843009213693952 2 ^ 62 = 4611686018427387904 2 ^ 63 = 9223372036854775808 2 ^ 64 = 9223372036854775808可以看出 unsigned __int64也不能获得正确的结果!
最后,难道真的没有办法计算pow(2,64)吗?
当然可以,就是用double或者float#include<iostream> #include<cmath> using namespace std; int main(){ for(int i=30;i<65;i++) { double d = pow(2,i)-1; cout<<"2 ^ "<<i<<"="<<d<<endl; } return 0; }结果:
2 ^ 45=3.51844e+013 2 ^ 46=7.03687e+013 2 ^ 47=1.40737e+014 2 ^ 48=2.81475e+014 2 ^ 49=5.6295e+014 2 ^ 50=1.1259e+015 2 ^ 51=2.2518e+015 2 ^ 52=4.5036e+015 2 ^ 53=9.0072e+015 2 ^ 54=1.80144e+016 2 ^ 55=3.60288e+016 2 ^ 56=7.20576e+016 2 ^ 57=1.44115e+017 2 ^ 58=2.8823e+017 2 ^ 59=5.76461e+017 2 ^ 60=1.15292e+018 2 ^ 61=2.30584e+018 2 ^ 62=4.61169e+018 2 ^ 63=9.22337e+018 2 ^ 64=1.84467e+019
使用double和float可以获得完全相同的结果。
double和float的区别有一下几点:
1.名字不同,double:双精度,float:单精度
2.大小不同,double占8个字节,float占4个字节,所以也意味着double的精度更高,范围更大
详情看这个:点击打开链接
现在有两个问题没解决:
1.为什么long(vc中的__int64)不能计算出正确的结果?例如有符号的2^63-1,无符号的2^64-1
2.为什么在2^54以后结果就出现失真?为什么是54而不是53或者55呢?
如果有知道的,请大牛不吝赐教。
相关文章推荐
- C语言几种常见数据类型的范围
- C语言几种常见数据类型的范围
- JAVA基本数据类型范围和float、double精度问题
- 几种常见的js数据类型转变
- 关于int范围中负数最小值的绝对值比整数最大值大初学C,问题源自:为什么C中的int类型(16位)的下溢下限为-32768而上溢上限却是32767。 首先说吧,32767很容易理解,32767=
- byte范围及8种常见数据类型
- 简单谈谈Python中的几种常见的数据类型
- 怎样知道基本数据类型的最大值 以及取值范围
- 解决Mybatis框架java.sql.SQLException: 数据大小超出此类型的最大值的问题
- 【转】各种数据类型的取值范围 C/C++标准库中定义的各个类型最大值最小值limit.h
- 【常见数据类型占多少字节问题】
- 基本数据类型常见问题
- Java基本数据类型——Java基本数据类型汇总、自动类型转换(指导图)、强制类型转型乱码问题、运算时类型提升容易犯的错误常见问题汇总
- Qt 常见的几种数据类型转换
- comparaTo()几种常见的数据类型比较
- 数据类型、运算符、表达式常见问题
- 常见的数据类型的范围
- 关于“Hibnerate报数据大小超出此类型的最大值”问题【已解决】
- 关于“Hibnerate报数据大小超出此类型的最大值”问题【已解决】
- java 常见的几种类型范围说明,char 型变量中能不能存贮一个中文汉字