float、double除法计算小数精确度问题

ava中的float和double类型在表示小数时存在精度问题,因为它们是基于二进制浮点数的IEEE 754标准实现的。BigDecimal类可以解决这个问题,它提供了精确的小数运算能力。

从float/double创建BigDecimal

避免直接使用float或double的构造方法,因为这会传递不精确的值。推荐使用字符串构造方法:

float f = 0.1f;
double d = 0.1;

// 不推荐:可能引入不精确的值
BigDecimal bd1 = new BigDecimal(f); 
BigDecimal bd2 = new BigDecimal(d);

// 推荐:使用字符串构造
BigDecimal bd3 = new BigDecimal("0.1");
BigDecimal bd4 = new BigDecimal(Float.toString(f));
BigDecimal bd5 = new BigDecimal(Double.toString(d));
 

设置精度和舍入模式

BigDecimal的运算需要指定舍入模式,常见的模式包括:

  1. RoundingMode.UP(进位):不管保留数字后面是大是小(0除外)都会进1。结果会向原点的反方向对齐,正数向正无穷方向对齐,负数向负无穷方向对齐。
  2. RoundingMode.DOWN(舍去):将要丢掉的数字直接丢掉。结果会向原点的反方向对齐,正数向正无穷方向对齐,负数向负无穷方向对齐。
  3. RoundingMode.CEILING(天花板):向上取整,即不管保留数字后面是大是小(0除外)都会进1,正数不变化,负数向正无穷方向对齐。
  4. RoundingMode.FLOOR(地板):向下取整,即将要丢掉的数字直接丢掉,正数向负无穷方向对齐,负数不变化。
  5. RoundingMode.HALF_UP(四舍五入):四舍五入,保留数字后面第一位是非零即进1。
  6. RoundingMode.HALF_DOWN(半舍半入):保留数字后面第一位是非零即进1,如果第二位是5则进1。
  7. RoundingMode.HALF_EVEN(银行家舍入):四舍六入五留双,保留数字后面第一位是非零即进1,如果第二位是5则看第一位,是偶数则进1,否则舍去。
  8. RoundingMode.UNNECESSARY(必要):如果舍入后的结果不是原数则抛出异常。

以上就是BigDecimal中的八种RoundingMode,每种模式都有其特定的行为和用途。在使用BigDecimal进行高精度计算时,可以根据需要选择合适的舍入模式来保证计算的准确性和精度。

BigDecimal a = new BigDecimal("1.2345");
BigDecimal b = new BigDecimal("3.1415");

// 加法
BigDecimal sum = a.add(b);

// 减法
BigDecimal difference = a.subtract(b);

// 乘法
BigDecimal product = a.multiply(b);

// 除法,指定精度和舍入模式
BigDecimal quotient = a.divide(b, 4, RoundingMode.HALF_UP);
 

示例:百分数数字转换

将99.99%转换成小数0.9999,再将0.9999转换成99.99

        double p = 99.99;
        BigDecimal bP = new BigDecimal(String.valueOf(p));
        BigDecimal b100 = new BigDecimal(String.valueOf(100));
        BigDecimal bigDiv = bP.divide(b100);
        double d = bigDiv.doubleValue();
        System.out.println(bigDiv);//0.9999
        System.out.println(d);//0.9999

        BigDecimal dP = new BigDecimal(String.valueOf(d));

        BigDecimal s = dP.multiply(b100);
        double ss = s.doubleValue();
        System.out.println(s);//99.9900
        System.out.println(ss);//99.99

比较BigDecimal值

避免使用equals()方法,因为它会比较精度和值。使用compareTo()方法进行值比较:

BigDecimal x = new BigDecimal("1.0");
BigDecimal y = new BigDecimal("1.00");

// 不推荐:false,因为精度不同
boolean eq = x.equals(y);

// 推荐:0,表示值相等
int cmp = x.compareTo(y);
 

格式化BigDecimal输出

使用DecimalFormat可以控制BigDecimal的输出格式:

BigDecimal value = new BigDecimal("1234.5678");
DecimalFormat df = new DecimalFormat("#,##0.00");
String formatted = df.format(value);  // 输出:1,234.57
 

注意事项

  • BigDecimal是不可变对象,每次运算都会产生新对象
  • 对于金融计算等需要精确小数的场景,优先使用BigDecimal
  • 构造BigDecimal时尽量使用字符串而非float/double字面量
  • 运算时明确指定舍入模式,避免出现ArithmeticException
内容概要:本文围绕可变桨叶四旋翼无人机的规范控制与点对点运动模拟展开,重点研究优化推力分配策略在翻转动作中的应用与性能比较。通过Matlab代码实现,构建了四旋翼动力学模型,并设计了多种控制算法以实现精确的姿态调整与轨迹跟踪。研究对比了不同推力分配方案在执行高机动性翻转动作时的稳定性、能耗效率与响应速度,旨在提升无人机在复杂飞行任务中的动态性能与控制精度。该仿真研究为无人机飞控系统的设计与优化提供了理论依据和技术支持。; 适合人群:具备一定自动控制理论基础和Matlab编程能力,从事无人机控制、飞行器动力学或机器人系统研究的科研人员及研究生。; 使用场景及目标:① 实现四旋翼无人机在三维空间中的精确点对点运动控制;② 对比分析不同推力分配策略在执行翻转等高难度动作时的控制效果与能耗表现,优化飞行性能;③ 为无人机自主飞行、特技飞行及复杂环境下的机动控制提供算法验证平台。; 阅读建议:此资源以Matlab仿真为核心,建议读者结合相关控制理论知识,深入理解代码实现细节,重点关注动力学建模、控制律设计与推力分配模块。在学习过程中,应动手调试参数,复现文中翻转动作的仿真结果,并尝试拓展至其他复杂飞行任务,以深对无人机控制机理的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值