Double使用注意事项

目录

  • 数据精度问题
  • BigDecimal的正确使用
    • 构造陷阱
    • 数值比较
    • 除法
    • 舍入控制 `RoundingMode`

数据精度问题

Java开发中,Double类作为包装类用于处理双精度浮点数。浮点数double无法精确表示某些十进制小数(如0.1),导致运算结果出现误差

double a = 0.1;
double b = 0.2;
System.out.println(a + b); // 输出 0.30000000000000004,而非0.3

需要精确计算的场景需要使用:BigDecimal,并通过字符串构造避免初始精度丢失。

BigDecimal d1 = new BigDecimal("0.1");
BigDecimal d2 = new BigDecimal("0.2");
System.out.println(d1.add(d2)); // 0.3

Double 比较推荐使用 Double.compare(a, b)

double a = 0.1;
double b = 0.1;
System.out.println(a == b); // trueDouble aD = 0.1;
Double bD = 0.1;
System.out.println(aD == bD); // false
System.out.println(Double.compare(aD, bD) == 0); // true

BigDecimal的正确使用

对于需要精确计算的场景,使用BigDecimal

构造陷阱

避免用double构造BigDecimal,否则传入的是不精确的二进制值。

double v = 0.946; 
System.out.println(v); // 输出正确,0.946
// 直接转 BigDecimal,实际内部值是不精确的二进制值,导致截取3位小数结果错误
double vv = new BigDecimal(v).setScale(3, RoundingMode.DOWN).doubleValue();
System.out.println(vv); // 输出错误值 0.945

正确做法:BigDecimal(字符串构造)

double vvv = new BigDecimal(String.valueOf(v)).setScale(3, RoundingMode.DOWN).doubleValue();
System.out.println(vvv); // 输出正确,0.946

数值比较

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("1");
System.out.println(a.compareTo(b) == 0); // true,数值相等

除法

必须指定舍入模式和精度,处理无限小数

BigDecimal a = new BigDecimal("10");
BigDecimal b = new BigDecimal("3");
// 指定保留4位小数,四舍五入
BigDecimal result = a.divide(b, 4, RoundingMode.HALF_UP); // 3.3333

不处理无限小数会抛出异常 ArithmeticException

BigDecimal a = new BigDecimal("10");
BigDecimal b = new BigDecimal("3");
a.divide(b); // 抛出 ArithmeticException

舍入控制 RoundingMode

RoundingMode.UP 远离零方向舍入 2.53, -2.5-3
RoundingMode.DOWN 向零方向舍入 2.52, -2.5-2
RoundingMode.CEILING 向正无穷方向舍入 2.53, -2.5-2
RoundingMode.FLOOR 向负无穷方向舍入 2.52, -2.5-3
RoundingMode.HALF_UP 四舍五入(常用) 2.53, 2.42
RoundingMode.HALF_DOWN 五舍六入 2.52, 2.63

示例

// 测试数值
BigDecimal number = new BigDecimal("2.55");
String label = "正数 2.55";
int newScale = 1;System.out.println("--- 测试数值: " + label + " ---");// UP:远离零方向舍入
System.out.println("UP          : " + number.setScale(newScale, RoundingMode.UP));// DOWN:向零方向舍入
System.out.println("DOWN        : " + number.setScale(newScale, RoundingMode.DOWN));// CEILING:向正无穷方向舍入
System.out.println("CEILING     : " + number.setScale(newScale, RoundingMode.CEILING));// FLOOR:向负无穷方向舍入
System.out.println("FLOOR       : " + number.setScale(newScale, RoundingMode.FLOOR));// HALF_UP:四舍五入
System.out.println("HALF_UP     : " + number.setScale(newScale, RoundingMode.HALF_UP));// HALF_DOWN:五舍六入
System.out.println("HALF_DOWN   : " + number.setScale(newScale, RoundingMode.HALF_DOWN));

结果展示,

--- 测试数值: 正数 2.55 ---
UP          : 2.6
DOWN        : 2.5
CEILING     : 2.6
FLOOR       : 2.5
HALF_UP     : 2.6
HALF_DOWN   : 2.5

负数注意 UP 和 CEILING,DOWN 和 FLOOR 的区别。

  • UP 是远离零方向(对负数是“向下舍入”,绝对值更大)。
  • CEILING 向正无穷方向(即对负数是“向上舍入”,更接近零),类似于数学中向上取整。
--- 测试数值: 负数 2.55 ---
UP          : -2.6
DOWN        : -2.5
CEILING     : -2.5
FLOOR       : -2.6
HALF_UP     : -2.6
HALF_DOWN   : -2.5

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/906927.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

8.2 线性变换的矩阵

一、线性变换的矩阵 本节将对每个线性变换 T T T 都指定一个矩阵 A A A. 对于一般的列向量,输入 v \boldsymbol v v 在空间 V R n \pmb{\textrm V}\pmb{\textrm R}^n VRn 中,输出 T ( v ) T(\boldsymbol v) T(v) 在空间 W R m \textrm{\pmb W}\…

【后端高阶面经:微服务篇】5、限流实战:高并发系统流量治理全攻略

一、限流阈值的三维度计算模型 1.1 系统容量基准线:压测驱动的安全水位 1.1.1 压力测试方法论 测试目标:确定系统在资源安全水位(CPU≤80%,内存≤70%,RT≤500ms)下的最大处理能力测试工具: 单机压测:JMeter(模拟10万并发)、wrk(低资源消耗)集群压测:LoadRunner …

同一无线网络下的设备IP地址是否相同?

在家庭和办公网络普及的今天,许多人都会好奇:连接同一个Wi-Fi的设备是否共享相同的IP地址?这个问题看似简单,实则涉及多个角度。本文将为您揭示其中的技术奥秘。 用一个无线网IP地址一样吗?同一无线网络(如…

git push出现 “HTTP 400 curl 22 The requested URL returned error: 400...“错误

错误内容是: 错误:RPC 失败。HTTP 400 curl 22 The requested URL returned error: 400 send-pack: unexpected disconnect while reading sideband packet 致命错误:远端意外挂断了 检查发现;文件大小5M,远低于100M&a…

对WireShark 中的UDP抓包数据进行解析

对WireShark 中的UDP抓包数据进行解析 本文尝试对 WireShark 中抓包的 UDP 数据进行解析。 但是在尝试对 TCP 中的 FTP 数据进行解析的时候,发现除了从端口号进行区分之外, 没有什么好的方式来进行处理。 import numpy as np import matplotlib.pyplot …

云原生安全基石:Linux进程隔离技术详解

🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 进程隔离是操作系统通过内核机制将不同进程的运行环境和资源访问范围隔离开的技术。其核心目标在于: 资源独占:确保…

云迹机器人底盘调用

云迹机器人底盘调用还是比较友好的,就是纯socket收发指令就能实现,今天实现一个底盘移动到指定点位功能。底盘的默认IP是192.168.10.10通讯端口是31001,测试机与底盘接入统一网络后直接发指令即可。本文给出两种语言调用源码,选择…

勇闯Chromium—— Chromium的多进程架构

问题 构建一个永不崩溃或挂起的渲染引擎几乎是不可能的,构建一个绝对安全的渲染引擎也几乎是不可能的。 从某种程度上来说,2006 年左右的网络浏览器状态与过去单用户、协作式多任务操作系统的状况类似。正如在这样的操作系统中,一个行为不端的应用程序可能导致整个系统崩溃…

MYSQL中的分库分表及产生的分布式问题

分库分表是分布式数据库架构中常用的优化手段,用于解决单库单表数据量过大、性能瓶颈等问题。其核心思想是将数据分散到多个数据库(分库)或多个表(分表)中,以提升系统的吞吐量、查询性能和可扩展性。 一&am…

GAMES104 Piccolo引擎搭建配置

操作系统:windows11 家庭版 inter 17 12 th 显卡:amd 运行内存:>12 1、如何构建? 在github下载:网址如下 https://github.com/BoomingTech/Piccolo 下载后安装 git、vs2022 Git Visual Studio 2022 IDE - …

页表:从虚拟内存到物理内存的转换

目录 引言 虚拟内存 页表 单级页表 页表项 单级页表的不足 二级页表 四级页表 快表TLB 结语 引言 一个系统中,CPU和内存是被所有进程共享的,而且一个系统中往往运行着多个进程。如果一个进程不小心写了另一个进程的内存,那么被写入…

互联网大厂Java求职面试:短视频平台大规模实时互动系统架构设计

互联网大厂Java求职面试:短视频平台大规模实时互动系统架构设计 面试背景介绍 技术总监(严肃脸): 欢迎来到我们今天的模拟面试,我是技术部的李总监,负责平台后端架构和高可用系统设计。今天我们将围绕一个…

网络段、主机段、子网掩码

子网掩码把 IP 切割成了网络段和主机段两部分。同一网段下的不同主机之间可以互通网络。 掩码 IPV4 默认情况下 IP 地址 192.168.0.x 可以分配 256 个主机地址(不考虑首尾两个特殊的地址时)。 假设我们只需要用到 8 个主机,就可以借助子网掩…

从零搭建SpringBoot Web 单体项目2、SpringBoot 整合数据库

系列文章 从零搭建SpringBoot Web单体项目【基础篇】1、IDEA搭建SpringBoot项目 从零搭建 SpringBoot Web 单体项目【基础篇】2、SpringBoot 整合数据库 目录 一、项目基础环境说明 二、数据库整合流程 1. 添加 MyBatis-Plus 相关依赖(pom.xml) 2…

4款顶级磁力下载工具,速度提升器,可以变下变播

今天给大家带来一些超给力的磁力下载工具,速度飞快,最高可达20MB/s,而且还能边下边播! 下载链接:夸克网盘分享(点击蓝色字体自行保存下载) 一、柚子下载 柚子下载界面干净,没有广…

怎样判断服务器网络质量的状态?

服务器存储着企业的重要数据信息,服务器的网络质量会影响到用户访问数据信息的速度,也决定着网站页面是否会出现卡顿或页面崩溃的情况,那我们对于服务器中网络质量的状态该如何进行判断呢? 服务器的网络状态通常是指服务器与外部网…

零基础入门Selenium自动化测试:自动登录edu邮箱

🌟 Selenium简单概述一下 Selenium 是一个开源的自动化测试工具,主要用于 Web 应用程序的功能测试。它能够模拟用户操作浏览器的行为(如点击按钮、填写表单、导航页面等),应用于前端开发、测试和运维领域。 特点 跨…

day36 python神经网络训练

目录 一、数据准备与预处理 二、数据集划分与归一化 三、构建神经网络模型 四、定义损失函数和优化器 五、训练模型 六、评估模型 在机器学习和深度学习的实践中,信贷风险评估是一个非常重要的应用场景。通过构建神经网络模型,我们可以对客户的信用…

如何确定是不是一个bug?

在软件测试过程中,我们经常会遇到一些异常现象,但并非所有异常都是Bug。如何准确判断一个问题是否属于Bug?本文将从Bug的定义、判定标准、常见误区和实战技巧四个方面展开,帮助测试工程师提高Bug判定的准确性。 1. Bug的定义:什么情况下算Bug? 一个Bug(缺陷)通常指软件…

Lombok与Jackson实现高效JSON序列化与反序列化

引言 在Java开发中,处理JSON数据是常见需求,而Jackson作为广泛使用的JSON库,能够高效地将Java对象与JSON互相转换。然而,传统的POJO(Plain Old Java Object)需要手动编写大量样板代码(如getter…