java 取余_Java 私藏避坑绝技之奇数性、浮点数

点击蓝色小字关注!  关注一下你就不会有bug!

奇数性

看下面代码时候是否能判断参数 i 是奇数?
1public static boolean isOdd(int i){ 
2  return i % 2 == 1; 
3}
答案是:No!看似正确的判断奇数,但是如果 i 是负数,那么它返回值都是 false 造成这种现象的是 => 从思想上固化,认为奇数只在正数范围,故判断负数将报错,在 C++ 中也是,负数取余还是负。在 Java 中取余操作定义产生的后果都满足下面的恒等式:
1//int数值a, 与非零int数值b 都满足下面的等式:
2(a / b) * b + (a % b) == a
从上面就可以看出,当取余操作返回一个非零的结果时,左右操作数具有相同的正负号,所以当取余在处理负数的时候,以及会考虑负号。 而上面的这个问题解决方法就是避免判断符号:
1public static boolean isOdd(int i){ 
2    return i % 2 != 0; 
3}

让结果与 0 比较,很容易避免正负号判断。

思考:在使用取余操作的时候要考虑符号对结果的影响。在运算中尝试使用 0 解决符号问题,在一定程度上避免符号对结果的影响。

浮点数产生的误差

看下面代码会打印出什么样的结果?

1public class Change{ 
2  public static void main(String args[]){ 
3    System.out.println(2.00 - 1.10); 
4  } 
5}

从主观上看,打印的结果必然是 0.90,然后这却是一个主观错误。对于 1.10 这个数,计算机只会使用近似的二进制浮点数表示,产生精度影响。从上面的例子中来看,1.10 在计算机中表示为 1.099999,这个 1.10 并没有在计算机中得到精确的表示。针对这个精度问题,我们可能会选择 System.out.printf("%.2f%n", 2.00 - 1.10); 解决。

尽管打印出来的是正确答案,但是依旧会暴露出一个问题:如果精度控制在 2.00 - 1.0010,那么精度误差依旧会出现。这里也说明使用 printf,计算机底层依旧是使用二进制的方式来计算,只不过这种计算提供了更好的近似值而已。

那么应该怎么解决这个问题呢?首先想到是使用 int 模拟小数每一位,然后计算,最后将结果又转化为小数,以此想到的就是使用 BigDecimal 类,它主要用于精确小数运算。

1import java.math.BigDecimal; 
2public class Change1{ 
3  public static void main(String args[]){ 
4    System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10"))); 
5  } 
6}
通过上面的代码就能得到一个精确的值。 注:使用 BigDecimal 的时候不要使用 BigDecimal(double d) 的构造方法,在 double 与 double 之间传值的时候依旧会引起精度损失,这是一个严重的问题。BigDecimal 底层采用的就是 int[],使用 String 的时候会将 String 不断取每一位存入 int[],使用 double 的时候同理将数字的每一位存入 int[],但是 double 本身存在误差,导致存入的数据会出现误差,例如 0.1 存入 double 就表示为 0.1000000099999999,因此不使用 double 类型的构造函数。 思考:对于精确要求不高的地方,完全可以使用 float/double,但是对于要求精度的计算,比如货币则一定要使用 int、long、BigDecimal。 54bec65ac2c5b3adc4f108269205b5ee.gif▼往期精彩回顾▼程序猿12个人艰不拆的真相Java异常处理中对于finally的一些思考

8f6dfcee46bac79644a30ab8cf7249ed.png

2fb2d31c64b4fd8dff8a70e9fbfe7525.png

ba6b6819aa7b03f4578177ea697c1969.png点击左下角阅读原文查看历史经典技术问题汇总,看完顺手走一波PYQ呀~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值