java中的getnumber怎么⽤_Java的数值类型Number操作详解Java的基本数据类型分为两⼤类: boolean 类型和数值类型。⽽数值类型⼜可以分为整数类型和浮点类型,整数类型⾥的字符类型也可被单独对待。因此常把Java⾥的基本数据类型分为4类。
数值类型有byte,short,int,long,float,double和char,每种Number类型都有它的范围,我们看下java中Number类型的范围:
考虑到我们最常⽤的int操作,虽然int的范围够⼤,但是如果我们在做⼀些int操作的时候还是可能超出int的范围。
超出了int范围会发送什么事情呢?看下⾯的例⼦:
publicvoidtestIntegerOverflow(){
System.out.println(Integer.MAX_VALUE+1000);
}
运⾏结果:-2147482649。
很明显Integer.MAX_VALUE+1000将会超出Integer的最⼤值范围,但是我们没有得到异常提醒,反⽽得到了⼀个错误的结果。
正确的操作是如果我们遇到了Overflow的问题,需要抛出异常:ArithmeticException。
怎么防⽌这种IntegerOverflow的问题呢?⼀般来讲,我们有下⾯⼏种⽅式。
第⼀种⽅式:在做Integer操作之前,进⾏预判断是否超出范围:
举个例⼦:
staticfinalintsafeAdd(intleft,intright){
if(right>0?left>Integer.MAX_VALUE-right
:left
}
returnleft+right;
}
上⾯的例⼦中,我们需要进⾏两个整数相加操作,在相加之前,我们需要进⾏范围的判断,从⽽保证计算的安全性。
第⼆种⽅式:使⽤Math的addExact和multiplyExact⽅法:
Math的addExact和multiplyExact⽅法已经提供了Overflow的判断,我们看下addExact的实现:publicstaticintaddExact(intx,inty){
intr=x+y;
// HD 2-12 Overflow iff both arguments have the opposite sign of the result
if(((x^r)&(y^r))<0){
thrownewArithmeticException("integer overflow");
}
returnr;
}
看下怎么使⽤:
public int addUseMath(int a, int b){
return Math.addExact(a,b);
}
第三种⽅式:向上转型
既然超出了Integer的范围,那么我们可以⽤范围更⼤的long来存储数据。
publicstaticlongintRangeCheck(longvalue){
if((valueInteger.MAX_VALUE)){
thrownewArithmeticException("Integer overflow");
bigdecimal转换为integer}
returnvalue;
}
publicintaddUseUpcasting(inta,intb){
return(int)intRangeCheck((long)a+(long)b);
}
上⾯的例⼦中,我们将a+b转换成了两个long相加,从⽽保证不溢出范围。
然后进⾏⼀次范围⽐较,从⽽判断相加之后的结果是否仍然在整数范围内。
第四种⽅式:使⽤BigInteger
publicintuseBigInteger(inta,intb){
returnBigInteger.valueOf(a).add(BigInteger.valueOf(b)).intValue();
}
区分位运算和算数运算
我们通常会对Integer进⾏位运算或者算数运算。虽然可以进⾏两种运算,但是最好不要将两种运算同时进⾏,这样会造成混淆。
⽐如下⾯的例⼦:
x+=(x<<1)+1;
上⾯的例⼦是想做什么呢?其实它是想将3x+1的值赋给x。
但是这样写出来让⼈很难理解,所以我们需要避免这样实现。
再看下⾯的⼀个例⼦:
publicvoidtestBitwiseOperation(){
inti=-10;
System.out.println(i>>>2);
System.out.println(i>>2);
System.out.println(i/4);
}
本来我们想做的是将i除以4,结果发现只有最后⼀个才是我们要的结果。
我们来解释⼀下,第⼀个i>>>2是逻辑右移,将会把最左边的填充成0,所以得出的结果是⼀个正值1073741821。
第⼆个i>>2是算数右移,最左边的还是会填充成1,但是会向下取整,所以得出结果是-3.
直接使⽤i/4,我们是向上取整,所以得出结果是-2.
注意不要使⽤0作为除数
我们在使⽤变量作为除数的时候,⼀定要注意先判断是否为0.
兼容C++的⽆符号整数类型
在java中只有16位的char表⽰的是⽆符号整数,⽽int实际上表⽰的是带符号的整数。
⽽在C或者C++中是可以直接表⽰⽆符号的整数的,那么,如果我们有⼀个32位的⽆符号整数,该怎么⽤java来处理呢?
publicintreadIntWrong(DataInputStreamis)throwsIOException{
}
看上⾯的例⼦,我们从Stream中读取⼀个int值,如果是⼀个32位的⽆符号整数,那么读出来int就变成了有符号的负整数,这和我们的期望是相符的。
考虑⼀下,long是64位的,我们是不是可以使⽤long来表⽰32位的⽆符号整数呢?
publiclongreadIntRight(DataInputStreamis)throwsIOException{
看上⾯的例⼦,我们返回的是long,如果将32位的int转换成为64位的long,会⾃动根据符号位进⾏补全。
所以这时候我们需要和0xFFFFFFFFL进⾏mask操作,将⾼32位重置为0.
NAN和INFINITY
在整型运算中,除数是不能为0的,否则直接运⾏异常。但是在浮点数运算中,引⼊了NAN和INFINITY的概念,我们来看⼀下Double和Float中的定义。
publicstaticfinaldoublePOSITIVE_INFINITY=1.0/0.0;
publicstaticfinaldoubleNEGATIVE_INFINITY=-1.0/0.0;
publicstaticfinaldoubleNaN=0.0d/0.0;
publicstaticfinalfloatPOSITIVE_INFINITY=1.0f/0.0f;
publicstaticfinalfloatNEGATIVE_INFINITY=-1.0f/0.0f;
publicstaticfinalfloatNaN=0.0f/0.0f;
1除以0就是INFINITY,⽽0除以0就是NaN。
接下来,我们看⼀下NAN和INFINITY的⽐较:
publicvoidcompareInfinity(){
System.out.println(Double.POSITIVE_INFINITY==Double.POSITIVE_INFINITY);
}
运⾏结果是true。
publicvoidcompareNaN(){
System.out.println(Double.NaN==Double.NaN);
}
运⾏结果是false。
可以看到NaN和NaN相⽐是false。
那么我们怎么⽐较NaN呢?
别急,Double提供了⼀个isNaN⽅法,我们可以这样使⽤:
System.out.println(Double.isNaN(Double.NaN));
接下来我们看⼀个在代码中经常会⽤到的⼀个Double解析:
publicvoidincorrectParse(StringuserInput){
doubleval=0;
try{
val=Double.valueOf(userInput);
}catch(NumberFormatExceptione){
}
//do something for val
这段代码有没有问题?咋看下好像没有问题,但是,如果我们的userInput是NaN,Infinity,或者-Infinity,Double.valueOf是可以解析得到结果的。
publicvoidtestNaN(){
System.out.println(Double.valueOf("NaN"));
System.out.println(Double.valueOf("Infinity"));
System.out.println(Double.valueOf("-Infinity"));
}
运⾏输出:
NaN
Infinity
-Infinity
所以,我们还需要额外去判断NaN和Infinity:
publicvoidcorrectParse(StringuserInput){
doubleval=0;
try{
val=Double.valueOf(userInput);
}catch(NumberFormatExceptione){
}
if(Double.isInfinite(val)){
// Handle infinity error
}
if(Double.isNaN(val)){
// Handle NaN error
}
//do something for val
}
不要使⽤float或者double作为循环的计数器
考虑下⾯的代码:
for(floatx=0.1f;x<=1.0f;x+=0.1f){
System.out.println(x);
}
上⾯的代码有什么问题呢?
我们都知道java中浮点数是不准确的,但是不⼀定有⼈知道为什么不准确。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论