复合双重错误

总览

在上一篇文章中,我概述了为什么BigDecimal大部分时间都不是答案。 虽然可以构造double会产生错误的情况,但在BigDecimal遇到错误的情况下构造情况也一样容易。

BigDecimal更容易正确,但更容易出错。

轶事证据表明,初级开发人员在正确使用BigDecimal时不会像在四舍五入时获得两倍的麻烦一样。 但是,我对此表示怀疑,因为在BigDecimal中,错误也容易被忽略。

让我们以这个例子为例,其中double会产生错误的答案。

double d = 1.00;
d /= 49;
d *= 49 * 2;
System.out.println("d=" + d);BigDecimal bd = BigDecimal.ONE;
bd = bd .divide(BigDecimal.valueOf(49), 2, BigDecimal.ROUND_HALF_UP);
bd = bd.multiply(BigDecimal.valueOf(49*2));
System.out.println("bd=" + bd);

版画

d=1.9999999999999998
bd=1.96

在这种情况下,double看起来是错误的,它需要四舍五入,这将给出2.0的正确答案。 但是BigDecimal看起来正确,但这不是由于表示错误。 我们可以更改除法以使用更高的精度,但是尽管可以控制该误差有多小,但总会出现表示错误。

您必须确保数字是实数并使用四舍五入。

即使使用BigDecimal,也必须使用适当的舍入。 假设您有一笔$ 1,000,000的贷款,并且每天要申请0.0005%的利息。 该帐户只能有一个整数,因此需要四舍五入才能使这笔钱成为实际金额。 如果不这样做,需要多长时间才能产生1美分的差异?

double interest = 0.0005;
BigDecimal interestBD = BigDecimal.valueOf(interest);double amount = 1e6;
BigDecimal amountBD = BigDecimal.valueOf(amount);
BigDecimal amountBD2 = BigDecimal.valueOf(amount);long i = 0;
do {System.out.printf("%,d: BigDecimal: $%s, BigDecimal: $%s%n", i, amountBD, amountBD2);i++;amountBD = amountBD.add(amountBD.multiply(interestBD).setScale(2, BigDecimal.ROUND_HALF_UP));amountBD2 = amountBD2.add(amountBD2.multiply(interestBD));} while (amountBD2.subtract(amountBD).abs().compareTo(BigDecimal.valueOf(0.01)) < 0);
System.out.printf("After %,d iterations the error was 1 cent and you owe %s%n", i, amountBD);

最终打印

8: BigDecimal: $1004007.00, BigDecimal: $1004007.00700437675043756250390625000000000000000
After 9 iterations the error was 1 cent and you owe 1004509.00

您可以四舍五入结果,但是即使您使用BigDecimal,这也掩盖了您差一分钱的事实。

double最终出现表示错误

即使您使用适当的舍入,double也会给您不正确的结果。 它比上一个示例晚得多。

double interest = 0.0005;
BigDecimal interestBD = BigDecimal.valueOf(interest);
double amount = 1e6;
BigDecimal amountBD = BigDecimal.valueOf(amount);
long i = 0;
do {System.out.printf("%,d: double: $%.2f, BigDecimal: $%s%n", i, amount, amountBD);i++;amount = round2(amount + amount * interest);amountBD = amountBD.add(amountBD.multiply(interestBD).setScale(2, BigDecimal.ROUND_HALF_UP));
} while (BigDecimal.valueOf(amount).subtract(amountBD).abs().compareTo(BigDecimal.valueOf(0.01)) < 0);
System.out.printf("After %,d iterations the error was 1 cent and you owe %s%n", i, amountBD);

最终打印

22,473: double: $75636308370.01, BigDecimal: $75636308370.01
After 22,474 iterations the error was 1 cent and you owe 75674126524.20

从IT角度来看,我们有一个错误的误差,从业务角度来看,我们有一个客户超过9年没有还款,并且还欠银行756亿美元,足以使该银行倒闭。 如果只有IT人员使用过BigDecimal !?

结论

我的最终建议是,您应该使用自己喜欢的东西,不要忘记取整,不要使用实数,而不要使用任何数学运算法则,例如,我可以赚一分钱,还是可以交易几分之一的份额。 不要忘记业务视角。 您可能会发现BigDecimal对您的公司,项目或团队更有意义。

不要以为BigDecimal是唯一的方法,不要以为双面问题也不适用于BigDecimal。 BigDecimal并不是最佳实践编码的门票,因为自满是引入错误的肯定方法。

翻译自: https://www.javacodegeeks.com/2014/07/compounding-double-error.html

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

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

相关文章

vue入门学习示例

鄙人一直是用angular框架的&#xff0c;所以顺便比较了一下。 1 <!DOCTYPE html>2 <html lang"en">3 <head>4 <meta charset"UTF-8">5 <title>vue实践</title>6 <script src"http://cdn.bootcss.…

项目实战报异常Exception及决绝方案

1、报LifecycleException&#xff0c;再配置一下jdk即可&#xff0c;然后再手动添加maven 解决方法&#xff1a; 然后,手动添加jar包 2、maven 项目,右键maven build启动项目的时候&#xff0c;报下面错误&#xff0c;没有在pom配置tomcat7插件 3、报找不到beans插件:更新一下项…

世界主要遥感卫星

世界主要遥感卫星QuickbirdSpot-4Spot-4法国“太阳神”1A神舟飞船神舟飞船“哈勃”望远镜RADASAT神舟飞船国际空间站国际空间站 SPOT2Shutsacn IKONOS CBERS-1JersSpot-4 “哈勃”望远镜 CBERS-1 Landsat 5美国“KH-11”侦察卫星 Spot-5 ERS Landsat 7OrbView-3 美国间谍卫星…

VMware配置linux网络步骤

1.我们要用桥接网络模式 2.设置桥接网络&#xff0c;VMnet1或者VMnet0就是桥接网络&#xff0c;我们用的就是桥接 VMnet8是NAT 在上面的图配置好ip和dns&#xff0c;要与windowss是同一个网段&#xff0c;网关一般不设置 3.设置linux网络里面设置这4项&#xff0c;记住dns可以不…

使用IntelliJ书签

这是有关IntelliJ的精美书签功能的快速帖子。 IntelliJ使您可以为单行代码添加书签。 将某行添加为书签后&#xff0c;您可以使用多种方法直接跳回到该行。 因此&#xff0c;最好在您经常使用的代码位置添加书签。 要创建一个新书签&#xff0c;只需在代码编辑器中按F11键。 …

用js写水仙花数

...js//输入一个三位数&#xff0c;水仙花数就是个位的三次方 十为的三次方 百位的三次方之和等于本身console.log(请输入一个三位数&#xff1a;);let a readline.question();if (a > 100 && a < 999) {if (parseInt(a / 100) ** 3 parseInt(a % 100 / 10) ** …

keras 打印模型图

keras中可以使用 from keras.utils import plot_model plot_model(model,to_filemodel_auth.png,show_shapesTrue) #show_shapesTrue可以把输入输出的shape一起打印 注意&#xff0c;最好是给每个层命名&#xff0c;命名好之后打印出来的才会带名字。程序运行的时候也有一定的指…

C# -- 多线程向同一文件写入

1. 多线程向同一文件写入Log. public delegate void AsyncLog(string str1, string str2);private void Test() {Console.WriteLine("Test Start...");for (int i 0; i < 100; i){AsyncLog asyLog1 new AsyncLog(WriteLog);asyLog1.BeginInvoke("EventActi…

Java中的命名参数

创建具有许多参数的方法是一个主要的缺点。 每当需要创建这样的方法时&#xff0c;就在空气中闻一闻&#xff1a;这是代码的味道。 强化单元测试&#xff0c;然后进行重构。 没有借口&#xff0c;没有屁股。 重构&#xff01; 使用构建器模式&#xff0c;甚至更好地使用Fluent …

CSS学习笔记3:选择器及优先级

CSS选择器的类型&#xff1a;标签选择器类选择器ID选择器全局选择器群组选择器后代选择器 1.标签选择器&#xff1a;以HTML的标签作为选择器&#xff0c;凡是选择了一个标签&#xff0c;那么所有这个标签的内容都是用了css样式用法很简单&#xff0c;直接在style中 标签{}即可声…

Eclipse开发,编译,打包常见问题总结------持续更新

在使用Eclipse开发&#xff0c;编译&#xff0c;打包常见问题如下&#xff1a; 1、 保证本地开发的客户端与服务端使用的jdk版本一致 2、 保证本地开发的客户端与服务端使用的依赖jar包版本一致&#xff08;比如本地thrift 客户端使用的libthrift版本和服务端使用的libthrift…

ECMA-335 (CLI) 标准 读书笔记——总结CLI类型系统(上)

看到类型系统的概述时&#xff0c;就忍不住按图索骥&#xff0c;想搞清楚CLI如何定义的整个类型系统。于是翻遍了整个标准&#xff0c;将类型系统中最核心的、与运行平台密切相关的类型定义与说明整理了出来&#xff0c;以供理清思路。 标准的第四部指出&#xff0c;CLI的核心是…

流口水可执行模型

可执行模型是对引擎处理的Drools最低级别模型的重新设计。 在当前的系列&#xff08;最多6.x&#xff09;中&#xff0c;可执行模型在过去的8年中有机地增长了&#xff0c;从未真正成为最终用户的目标。 建议那些希望以编程方式编写规则的人通过代码生成和目标drl来完成&#x…

centos7安装openjdk8

首先&#xff0c;打开openjdk安装官网 http://openjdk.java.net/install/ 输入安装命令&#xff1a; su -c "yum install java-1.8.0-openjdk" 装完之后会有提示版本跟安装的路径&#xff1b;在/usr/lib/jvm下可以查看到对应的名字&#xff0c;ls-l 配置环境变量&…

CSB文件上传漏洞 -->Day4(图片挂马)

22二号&#xff0c;冬至啦&#xff0c;深圳这边只有5&#xff08;尊嘟好冷啊&#xff09;&#xff0c;写这篇文章的时候都已经是凌晨一点了&#xff0c;相信大部分的人都在温暖的被窝里面了吧&#xff01;&#xff01;&#xff08;可怜的我&#xff0c;还得写writeup&#xff0…

微信小程序禁止刷新之后苹果端还可以下拉的问题

一、问题描述 最近在做一个小程序项目&#xff0c;需要禁止下拉刷新&#xff0c;于是在page.json里面添加了这段话 "enablePullDownRefresh":false 全局关闭下拉刷新&#xff0c;这段话确实禁止了下拉刷新&#xff0c;无论是安卓手机端还是苹果端&#xff0c;但是在…

Win32 Application和Win32 Console Application的区别

Win32 Application和Win32 Console Application都是工作在32位Windows环境的程序。其中Win32 Application就是普通的常见的窗口应用程序&#xff0c;当然有的界面做得比较个性化&#xff0c;比如圆形的、不规则形状的……它们都是所谓的GUI(Graphics User Interface图形用户接口…

调试OpenJDK

knowyourmeme.com/photos/531557 THX为mihn 有时调试Java代码还不够&#xff0c;我们需要逐步了解Java的本机部分。 我花了一些时间来实现JDK的正确状态&#xff0c;所以简短的描述可能对开始旅行的人很有用。 我将使用全新的OpenJDK 9&#xff01; 首先&#xff0c;您必须通过…

算法题解:旋转数组的最小数字

题目描述 把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转&#xff0c;输出旋转数组的最小元素。 解题思路 将旋转数组对半分可以得到一个包含最小元素的新旋转数组&#xff0c;以及一个非递减排序的数组。新…

函数的自执行,变量提升和函数提升

其实之前虽然刚开始学习JavaScript的时候经常看到function add(){}、var addfunction(){}、function(){}之类的这种写法&#xff0c;但是具体是什么叫什么却没有去考虑过这个问题…… function add(){}这种写法叫做函数声明 var addfunction(){}这种写法叫做函数表达式 fun…