java bigdecimal负数转正数_Java 大神的十个私藏避坑绝技

本文探讨了Java中关于数字处理的一些常见问题和陷阱,包括奇数性判断的错误、浮点数精度误差、长整数溢出、long类型的小写'l'混淆、类型转换中的数值变化、不建议的编程技巧、混合运算的隐患、隐式类型转换的风险、字符串加法的误解以及"==”运算符的误用。作者提出了解决这些问题的建议,特别强调了使用BigDecimal进行精确小数运算的重要性,并提醒开发者在处理数字运算时需谨慎对待类型转换和操作顺序。
摘要由CSDN通过智能技术生成

28afcfe1e66e77095381082b9811a70c.png

注:本文来自粉丝[菜鸟逆袭]投稿

1.奇数性

看下面代码时候是否能判断参数 i 是奇数?

public static boolean isOdd(int i){ 
  return i % 2 == 1; 
}

答案是: No!
看似正确的判断奇数, 但是如果 i 是负数, 那么它返回值都是false
造成这种现象的是 => 从思想上固化, 认为奇数只在正数范围, 故判断负数将报错, 在C++中也是, 负数取余还是负.
在Java中取余操作定义产生的后果都满足下面的恒等式:

int数值a, 与非零int数值b 都满足下面的等式:
(a / b) * b + (a % b) == a

从上面就可以看出, 当取余操作返回一个非零的结果时, 左右操作数具有相同的正负号, 所以当取余在处理负数的时候, 以及会考虑负号.

而上面的这个问题, 解决方法就是避免判断符号:

public static boolean isOdd(int i){ 
 return i % 2 != 0; 
}

让结果与0比较, 很容易避免正负号判断.思考:
1.在使用取余操作的时候要考虑符号对结果的影响
2.在运算中, 尝试使用0解决符号问题, 在一定程度上避免符号对结果的影响

2.浮点数产生的误差

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

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

从主观上看, 打印的结果必然是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类, 它主要用于精确小数运算.

import java.math.BigDecimal; 
public class Change1{  
 public static void main(String args[]){ 
  System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10"))); 
 } 
}

通过上面的代码就能得到一个精确的值.注: 使用BigDecimal的时候, 不要使用BigDecimal(double d)的构造方法, 在double与double之间传值的时候依旧会引起精度损失. 这是一个严重的问题.
BigDecimal底层采用的就是int[], 使用String的时候, 会将String不断取每一位存入int[], 使用double的时候, 同理将数字的每一位存入int[], 但是double本身存在误差, 导致存入的数据会出现误差,例: 0.1存入double就表示为0.1000000099999999, 因此不使用double类型的构造函数思考:
当然对于精确要求不高的地方, 完全可以使用float/double, 但是对于要求精度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值