当前位置: 首页 > news >正文

珠宝网站策划挂别人公司做网站可以吗

珠宝网站策划,挂别人公司做网站可以吗,wordpress 媒体插件,品牌推广的步骤目录 问题现象根本原因详细分析实际验证解决方案最佳实践总结 一开始看到这个说法的时候我还不相信,还以为之前我学的都错完了,研究之后才明白为什么 问题现象 令人困惑的计算结果 public class FloatPrecisionDemo {public static void main(Strin…

目录

  • 问题现象
  • 根本原因
  • 详细分析
  • 实际验证
  • 解决方案
  • 最佳实践
  • 总结

一开始看到这个说法的时候我还不相信,还以为之前我学的都错完了,研究之后才明白为什么

问题现象

令人困惑的计算结果

public class FloatPrecisionDemo {public static void main(String[] args) {// 这些看似简单的计算,结果却出人意料System.out.println("0.05 + 0.01 = " + (0.05 + 0.01));System.out.println("0.1 + 0.2 = " + (0.1 + 0.2));System.out.println("1.0 - 0.9 = " + (1.0 - 0.9));System.out.println("0.3 * 3 = " + (0.3 * 3));}
}

运行结果

0.05 + 0.01 = 0.060000000000000005
0.1 + 0.2 = 0.30000000000000004
1.0 - 0.9 = 0.09999999999999998
0.3 * 3 = 0.8999999999999999

等等!这些结果明显不对! 0.05 + 0.01 应该等于 0.06,为什么会出现这么多小数位?

根本原因

1. 二进制表示的局限性

十进制转二进制的精度问题
0.05 (十进制) = 0.0001100110011001100110011001100110011001100110011001101... (二进制)
0.01 (十进制) = 0.00000010100011110101110000101000111101011100001010001111... (二进制)

关键问题:这些小数在二进制中是无限循环小数,无法精确表示!

为什么会出现无限循环?
// 以0.05为例,转换为二进制的过程:
// 0.05 × 2 = 0.1  → 整数部分0,小数部分0.1
// 0.1 × 2 = 0.2   → 整数部分0,小数部分0.2
// 0.2 × 2 = 0.4   → 整数部分0,小数部分0.4
// 0.4 × 2 = 0.8   → 整数部分0,小数部分0.8
// 0.8 × 2 = 1.6   → 整数部分1,小数部分0.6
// 0.6 × 2 = 1.2   → 整数部分1,小数部分0.2
// 0.2 × 2 = 0.4   → 循环开始...// 结果:0.05 = 0.0001100110011001100110011001100110011001100110011001101...

2. IEEE 754浮点数标准

double类型的存储格式
64位 = 1位符号位 + 11位指数位 + 52位尾数位
精度限制
// double类型只能精确表示有限位数
// 对于0.05和0.01,在二进制中都是无限循环小数
// 存储时会被截断,导致精度丢失// 0.05在double中的实际存储值:
// 0.05000000000000000277555756156289135105907917022705078125// 0.01在double中的实际存储值:
// 0.01000000000000000020816681711721685132943093776702880859375

详细分析

1. 0.05的二进制表示

// 0.05的二进制表示(无限循环)
// 0.0001100110011001100110011001100110011001100110011001101...// 转换为科学计数法
// 1.1001100110011001100110011001100110011001100110011010 × 2^(-5)// 在double中存储时,52位尾数无法完全表示这个无限循环
// 导致精度丢失

2. 0.01的二进制表示

// 0.01的二进制表示(无限循环)
// 0.00000010100011110101110000101000111101011100001010001111...// 转换为科学计数法
// 1.0100011110101110000101000111101011100001010001111011 × 2^(-7)// 同样存在精度丢失

3. 相加过程

// 0.05 + 0.01 的实际计算过程
// 由于精度丢失,实际计算的是近似值
// 结果:0.060000000000000005// 详细过程:
// 0.05 (存储值) = 0.05000000000000000277555756156289135105907917022705078125
// 0.01 (存储值) = 0.01000000000000000020816681711721685132943093776702880859375
// 相加结果 = 0.060000000000000004991640087923096656986236572265625

实际验证

1. 更多浮点数精度问题

public class FloatPrecisionTest {public static void main(String[] args) {System.out.println("=== 浮点数精度问题演示 ===");// 基本运算System.out.println("0.1 + 0.2 = " + (0.1 + 0.2));System.out.println("0.05 + 0.01 = " + (0.05 + 0.01));System.out.println("1.0 - 0.9 = " + (1.0 - 0.9));System.out.println("0.3 * 3 = " + (0.3 * 3));// 比较问题double a = 0.1 + 0.2;double b = 0.3;System.out.println("0.1 + 0.2 == 0.3: " + (a == b));// 累积误差double sum = 0.0;for (int i = 0; i < 10; i++) {sum += 0.1;}System.out.println("0.1累加10次 = " + sum);System.out.println("sum == 1.0: " + (sum == 1.0));}
}

运行结果

=== 浮点数精度问题演示 ===
0.1 + 0.2 = 0.30000000000000004
0.05 + 0.01 = 0.060000000000000005
1.0 - 0.9 = 0.09999999999999998
0.3 * 3 = 0.8999999999999999
0.1 + 0.2 == 0.3: false
0.1累加10次 = 0.9999999999999999
sum == 1.0: false

2. 使用BigDecimal解决

import java.math.BigDecimal;
import java.math.RoundingMode;public class BigDecimalSolution {public static void main(String[] args) {System.out.println("=== BigDecimal精确计算 ===");// 正确的BigDecimal使用方式BigDecimal a = new BigDecimal("0.05");BigDecimal b = new BigDecimal("0.01");BigDecimal result = a.add(b);System.out.println("BigDecimal: 0.05 + 0.01 = " + result);BigDecimal c = new BigDecimal("0.1");BigDecimal d = new BigDecimal("0.2");System.out.println("BigDecimal: 0.1 + 0.2 = " + c.add(d));// 错误的BigDecimal使用方式BigDecimal wrong1 = new BigDecimal(0.05);BigDecimal wrong2 = new BigDecimal(0.01);BigDecimal wrongResult = wrong1.add(wrong2);System.out.println("错误方式: " + wrongResult);}
}

运行结果

=== BigDecimal精确计算 ===
BigDecimal: 0.05 + 0.01 = 0.06
BigDecimal: 0.1 + 0.2 = 0.3
错误方式: 0.060000000000000004991640087923096656986236572265625

解决方案

1. 使用BigDecimal(推荐)

正确的构造方式
// ✅ 正确方式:使用字符串构造器
BigDecimal correct1 = new BigDecimal("0.05");
BigDecimal correct2 = new BigDecimal("0.01");// ✅ 正确方式:使用valueOf方法
BigDecimal alsoCorrect = BigDecimal.valueOf(0.1);// ❌ 错误方式:使用double构造器
BigDecimal wrong = new BigDecimal(0.05);  // 会保留精度误差
完整的BigDecimal示例
import java.math.BigDecimal;
import java.math.RoundingMode;public class FinancialCalculator {public BigDecimal calculateInterest(BigDecimal principal, BigDecimal rate) {// 精确的利息计算return principal.multiply(rate).setScale(2, RoundingMode.HALF_UP);}public BigDecimal calculateTotal(BigDecimal price, int quantity) {// 精确的价格计算return price.multiply(new BigDecimal(quantity)).setScale(2, RoundingMode.HALF_UP);}public BigDecimal calculateDiscount(BigDecimal originalPrice, BigDecimal discountRate) {// 精确的折扣计算BigDecimal discount = originalPrice.multiply(discountRate);return originalPrice.subtract(discount).setScale(2, RoundingMode.HALF_UP);}
}

2. 浮点数比较的正确方式

public class FloatComparison {public static void main(String[] args) {double a = 0.1 + 0.2;double b = 0.3;//  错误的比较方式System.out.println("a == b: " + (a == b));  // false//  正确的比较方式:使用误差范围double epsilon = 1e-10;System.out.println("|a - b| < epsilon: " + (Math.abs(a - b) < epsilon));  // true//  正确的比较方式:使用BigDecimalBigDecimal bd1 = new BigDecimal("0.1").add(new BigDecimal("0.2"));BigDecimal bd2 = new BigDecimal("0.3");System.out.println("bd1.equals(bd2): " + bd1.equals(bd2));  // true}
}

3. 工具类封装

public class PrecisionUtils {private static final double EPSILON = 1e-10;/*** 比较两个浮点数是否相等*/public static boolean isEqual(double a, double b) {return Math.abs(a - b) < EPSILON;}/*** 比较两个浮点数是否相等(自定义误差范围)*/public static boolean isEqual(double a, double b, double epsilon) {return Math.abs(a - b) < epsilon;}/*** 舍入浮点数到指定小数位*/public static double round(double value, int places) {double scale = Math.pow(10, places);return Math.round(value * scale) / scale;}/*** 安全的浮点数加法*/public static BigDecimal safeAdd(double a, double b) {return new BigDecimal(String.valueOf(a)).add(new BigDecimal(String.valueOf(b)));}
}

最佳实践

1. 选择合适的数据类型

场景推荐类型原因
金融计算BigDecimal需要精确计算
科学计算double性能好,精度足够
整数计算int/long精确,性能最好
一般计算double平衡性能和精度

2. BigDecimal使用规范

public class BigDecimalBestPractices {//  正确的使用方式public BigDecimal calculatePrice(BigDecimal unitPrice, int quantity) {return unitPrice.multiply(new BigDecimal(quantity)).setScale(2, RoundingMode.HALF_UP);}//  使用常量避免重复创建private static final BigDecimal HUNDRED = new BigDecimal("100");private static final BigDecimal ZERO = BigDecimal.ZERO;public BigDecimal calculatePercentage(BigDecimal value, BigDecimal total) {if (total.equals(ZERO)) {return ZERO;}return value.multiply(HUNDRED).divide(total, 2, RoundingMode.HALF_UP);}//  处理除零异常public BigDecimal safeDivide(BigDecimal numerator, BigDecimal denominator) {if (denominator.equals(ZERO)) {throw new ArithmeticException("除数不能为零");}return numerator.divide(denominator, 10, RoundingMode.HALF_UP);}
}

3. 性能优化建议

public class PerformanceOptimization {// 对于不需要高精度的场景,使用基本类型public double calculateTemperature(double celsius) {return celsius * 9.0 / 5.0 + 32.0;  // 温度转换,精度要求不高}// 对于需要高精度的场景,使用BigDecimalpublic BigDecimal calculateInterest(BigDecimal principal, BigDecimal rate) {return principal.multiply(rate).setScale(2, RoundingMode.HALF_UP);}// 缓存常用的BigDecimal值private static final Map<String, BigDecimal> CACHE = new HashMap<>();public BigDecimal getCachedValue(String key) {return CACHE.computeIfAbsent(key, BigDecimal::new);}
}

常见陷阱

1. BigDecimal构造陷阱

//  陷阱1:使用double构造器
BigDecimal trap1 = new BigDecimal(0.1);  // 0.1000000000000000055511151231257827021181583404541015625//  陷阱2:使用float构造器
BigDecimal trap2 = new BigDecimal(0.1f);  // 0.100000001490116119384765625//  正确方式:使用字符串构造器
BigDecimal correct = new BigDecimal("0.1");  // 0.1//  正确方式:使用valueOf方法
BigDecimal alsoCorrect = BigDecimal.valueOf(0.1);  // 0.1

2. 舍入模式陷阱

BigDecimal number = new BigDecimal("3.14159");// 不同的舍入模式会产生不同结果
System.out.println("HALF_UP: " + number.setScale(2, RoundingMode.HALF_UP));      // 3.14
System.out.println("HALF_DOWN: " + number.setScale(2, RoundingMode.HALF_DOWN));  // 3.14
System.out.println("CEILING: " + number.setScale(2, RoundingMode.CEILING));      // 3.15
System.out.println("FLOOR: " + number.setScale(2, RoundingMode.FLOOR));          // 3.14

3. 比较陷阱

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("1.00");//  陷阱:equals方法比较值和精度
System.out.println("equals: " + a.equals(b));  // false//  正确方式:compareTo方法只比较值
System.out.println("compareTo: " + (a.compareTo(b) == 0));  // true

性能对比

1. 运算速度对比

public class PerformanceComparison {public static void main(String[] args) {int iterations = 1000000;// double运算long start1 = System.currentTimeMillis();double sum1 = 0.0;for (int i = 0; i < iterations; i++) {sum1 += 0.1;}long time1 = System.currentTimeMillis() - start1;// BigDecimal运算long start2 = System.currentTimeMillis();BigDecimal sum2 = BigDecimal.ZERO;for (int i = 0; i < iterations; i++) {sum2 = sum2.add(new BigDecimal("0.1"));}long time2 = System.currentTimeMillis() - start2;System.out.println("double运算时间: " + time1 + "ms");System.out.println("BigDecimal运算时间: " + time2 + "ms");System.out.println("性能差异: " + (time2 / time1) + "倍");}
}

2. 内存占用对比

类型内存占用精度适用场景
double8字节15-17位有效数字科学计算
BigDecimal可变(通常>20字节)任意精度金融计算

总结

核心要点

  1. 浮点数精度问题的根本原因

    • 某些十进制小数在二进制中是无限循环小数
    • IEEE 754标准只能存储有限位数
    • 存储时精度丢失导致计算误差
  2. 解决方案

    • 金融计算:使用BigDecimal
    • 科学计算:使用double,注意精度问题
    • 比较浮点数:使用误差范围或BigDecimal
  3. 最佳实践

    • 使用字符串构造BigDecimal
    • 选择合适的舍入模式
    • 注意性能权衡

实际应用建议

  • 金融系统:必须使用BigDecimal,确保计算精确
  • 科学计算:可以使用double,但要注意精度问题
  • 一般应用:根据精度要求选择合适的数据类型
  • 性能敏感:权衡精度和性能需求

记住这些关键点

  1. 0.05 + 0.01 ≠ 0.06 是正常的浮点数行为
  2. BigDecimal是金融计算的救星
  3. 字符串构造BigDecimal避免精度丢失
  4. 选择合适的舍入模式很重要
  5. 性能与精度需要权衡
http://www.dtcms.com/a/573457.html

相关文章:

  • Nine.fun全球KOL合作计划|以现实娱乐为舞台,构建Web3文化共创生态
  • 面向 Spring Boot 的 JVM 深度解析
  • SCRM工具测评:助力企业微信私域运营的核心功能解析
  • Web3.js 全面解析
  • 企业微信AI聊天agent:优化企业微信客户运营的推荐工具
  • 怎么做文化传播公司网站wordpress免费企业
  • springboot+vue3+redis+sse 后端主动推送数据
  • 潍坊网站优化培训四川在线
  • Azure AI服务成本分析指南
  • OceanBase数据库SQL调优
  • ④使用 PPTSYNC.exe 与华为手机拍照制作 GIF 动画
  • OceanBase all-in-one 4.2.0.0 安装教程(CentOS 7/EL7 一键部署详细步骤)​
  • 环保网站建设方案wordpress前端后端
  • 如何给网站备案山东网站搭建有限公司
  • veereal将在中国推广微型led技术
  • 对话 NuttX 创始人Gregory Nutt——openvela 与 NuttX 的 “双向奔赴” 新范式
  • 河北省地图谷歌seo网站优化
  • 湘潭知名网站建设网站静态页面生成
  • 从EMS看分布式能源发展:挑战与机遇并存
  • Java接入飞书发送通知消息
  • Vue.js 基础教程:从入门到实践
  • .net实现秒杀商品(Redis高并发)
  • 解决phpstudy 8.x软件中php8.2.9没有redis扩展的问题
  • 【MCP系列】飞书MCP使用
  • 阜新网站设计淮北市矿务局工程建设公司网站
  • 攻克维吾尔语识别的技术实践(多语言智能识别系统)
  • [Windows] 漫画翻译工具Saber Translator2.5.1
  • 手术机器人智能控制系统基本课时项目化课件(2025.08.25)
  • NATS安装与配置完全指南
  • 开发网站如何选需要注意什么汉川网页设计