64位整数全解

玛丽莲梦兔
661次浏览
2021年01月11日 09:25
最佳经验
本文由作者推荐

小班优秀教案-至关重要的近义词

2021年1月11日发(作者:石正林)



64位整形引起的混乱主要在两方面,一是数据类型的声明,二是输入输出。
首先是如果我们在自己机器上写程序的话,情况分类如下:
(1) 在win下的VC6.0里面,声明数据类型的时候应该写作
_ _int64 a;
输入输出的时候用 %I64d
scanf(”%I64d”,&a);
printf(”%I64d”,a);
(2) 在linux下的gccg++里面,数据类型声明写作
long long a;
输入输出时候用 %lld
(3) 在win下的其它IDE里面[包括高版本Visual Studio],数据类型声明用上面两种均可
输入输出用 %I64d
================== 以下可无视 =========================
以下是对这种混乱情况的解释,如无兴趣可以跳过
首先要说的是,和Java等语言不同,C C++本身并没有规定各数据类型的位数,只是限定了一
个大小关系,也就是规定从所占的bit数来说 ,short <= int <= long <= long long。至于具体哪种类型占
用多 少位,是由你所用的开发平台的编译器决定的。在现在的PC上一个通常的标准是,int和long
同 为32位,long long为64位。但是如果换到其它平台(如ARM)上,这个数字可能会有不同,类型
所占的大小可以用sizeof()运算符查看。
long long是C99标准中新引进 的数据类型,在古老的VC6.0中并没有这个类型,所以在VC6.0
中用”long long”会 发生编译错误。为了表示64位整数,VC6里采用的是微软自己搞出来的一个数
据类型,叫做__in t64,所以如果你是在VC6.0下编译的话,应该用__int64定义64位整型。新版的
Vis ual Studio已经支持long long了。GCC是支持long long的,我们在win系统中使用的其它IDE如
Dev-Cpp, Code::Blocks等等大多是采用的MinGW编译环境,它是与GCC兼容的,所以也支持long long
(另外为了与MS兼容,也支持__int64)。如果是在纯的linux下,就只能使用l ong long了。
关于使用printf的输入输出,这里就有一个更囧的情况。实际上只要记住 ,主要的区分在于操作
系统:如果在win系统下,那么无论什么编译器,一律用%I64d;如果在l inux系统,一律用%lld。这
是因为MS提供的库里使用的就是%I64d的方式,尽管Dev- Cpp等在语法上支持标准,但
也不得不使用MS提供的dll库来完成IO,所以就造成了这种情况。
==================== 无视至此 ===========================
那么对ACMer来说,最为关心的就是在各个OJ上交题应分别使用哪种方式了。其实方式只有
有限的几种:
如果服务器是linux系统,那么定义用long long,IO用%lld
如果服务器是win系统,那么声明要针对编译器而定:
+ 如果用MS系列编译器,声明用__int64 [现在新版的Visual Studio也支持long long了]
+ 如果用MinGW环境,声明用long long
+ 无论什么编译器,IO一律%I64d

下面把各大OJ情况列表如下:
1. TOJ : Linux系统
2. ZOJ : Linux系统
3. POJ : Wi n系统,语言如选择CC++,则用MS编译器[支持两种声明],如选择GCCG++,则
为MinG W


4. UVa : Linux系统
5. Ural: Win系统,MS编译器[支持两种声明]
6. SPOJ: Linux系统
7. SGU : Win系统,MS编译器[支持两种声明]

如果有不太清楚的情况可以先看看各OJ上的FAQ,通常会有说明。

另外,为了避免混乱,当数据量不大时,用cin, cout进行输入输出也是一种选择


错误经历:自己在作Equiptment Box时,因为输入数据长、宽均是小于5 0000的整数,因此就使用
int来作输入。这本身没有问题,但在求其斜边长时,使用的是sqrt (x * x + y * y),表面看是没有问
题,但结果一直是Wrong Answer。 后来将这一行改为pow( (pow(x, 2) + pow( y,3 ) ) , 0.5),就Accept
了!
错误原因:后来经johnbill和hewei的分析 ,x,y本身没有问题,不会越界,但使用sqrt(x*x +
y*y)时,里面的x*x 和 y*y则会超出int范围,造成溢出。而pow会将参数自动转换为double,就
不会出错。
避免:(1)以后均使用pow进行运算。(习惯)
(2)运算时,注意做强行转换。(比较麻烦)
(3)不管输入给的类型,直接用double来存储,就不会溢出了。这种方法表面看没有问题
,但直到这次比赛,才发现了一个很严重的问题!

2、double遇到过的问题错误经历

因为 double上限可达1.7e308 。而一般题目(非大数运算要求)均不可能超过其限,发
生溢出,所以之后我就在做题时,凡是遇到结果有些大时,均用double类型来保存,来避
免溢出。看起来,这样比较方便,因为我们在本机上是用VC++,而OnlineJudge是gcc,
它们支持的长整形类型不同,一个是_ _int64, 而一个是long long;处理格式也不同,I
64u 和 lld。而在这种情况下,“真正”的可以用double的话,那就可以将其统一起来。
但是……
昨天比赛C题时,自己也是这么递推和用double保存,但一直Wrong Answer。和递归能计算
出(太大的数据很耗时)的数据相比,都是正确的,不知原因何在。比赛 结束后,和别人结果对照了
一下,把double改成unsigned long long 就Accept了。
错译原因:这是因为:double类型的精度只有15位!!!它的上限 可以很大,但只能保证15位的
精度!double一般都可以保证最后结果小数点后7,8位都是精确 的。在数据( 50,50)以后,结
果都在20位以上,前面的位数是正确的,但后面的几位就会出现问题了!
解决方法(1)定义头文件,在本机上用__int64,提交时用long long
(2)本机上使用VAC编译( J ) (奇难用!)
(3) 反正绝对不能使用double来计数,尤其比较大的数,但可以利用它来测试最大数
据的范围大小,这样可以反过来帮助我们决定用什么类型来保存
(4)避免用float

3.浮点数问题总结

3.1 4舍5入的问题

在做Lifting the Stone时,题上要求保留到小数点两位,第三位作四舍五入,自己直接用
%.02来打,以为自动会四舍五入。但一直没过。加上处理之后就过了…….


原因:小数点后第三位为5时,会随机的作进位处理。
解决办法:如果题上要求了四舍五入,一定要记得进行处理:x = floor(x*100 + 0.5)100,
3.2 为5时,后一位奇数进位,偶数不进位:

这个JohnBIll讲过,一般不会有这种“浪费青春的题…..”。
解决办法:除了相当的灵活,多试,还需要运气了……
3.3浮点数判等
浮点数一般不可以判等,比较大小也要考虑误差,一般浮点数的比较可以写成fcmp函数:
int fcmp(double a,double b) {
if(a > b+eps) return 1;
if(a < b-eps) return -1;
return 0; }
这样,fcmp(a,b)>0 说明a>b,<0说明aeps 是一个很小的正数,具体取值按照实际情况而定,一般取1e-6。

3.4浮点数输出 < br>如果最后要求输出浮点数,要特别注意避免-0.00的出现。如果要求输出到小数点后两位,则输
出前要加上: if(fabs(ans) < 0.005) ans=0; 再输出。
3.5. 浮点数取整
对浮点数取整,要特别注意处理误差。如果其理论值就是整数,那么建 议加0.5后取整(若向上
取整,则减0.5)。否则,若理论值是5,由于误差算出来的是4.999 999,那么取整就会得到4。 如果
理论值不是整数,那么取整就只能加一个很小的正数(若向上取整 ,则要减去一个很小的正数),具
体值根据实际情况而定,有些时候甚至不需要处理误差


黄岩蜜桔-不要再来伤害我歌词


三秒钟之我是谁-朱自清作品


sos的意思-寒衣调歌词


在家创业做什么好-说明文阅读


吃板栗有什么好处-元宵的来历


阴阳五行-幼儿园区域活动


dnf镶嵌栏-喵小奇


重庆作文-演练