被辞退了,因为小数点计算错误

2023-12-28 00:28

本文主要是介绍被辞退了,因为小数点计算错误,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今年IT寒冬,大厂都裁员或者准备裁员,作为开猿节流主要目标之一,我们更应该时刻保持竞争力。为了抱团取暖,林老师开通了知识星球,并邀请我阿里、快手、腾讯等的朋友加入,分享八股文、项目经验、管理经验等,帮助大家提升技能,安稳度过这个寒冬,快扫描(长按)加入我们吧!

故事背景

今天我一个同事跟我吐槽,说他朋友因为程序问题,被公司辞退了,而且还没有任何补偿。我一听马上问,是删库跑路了嘛,这么严重。他说比这个还严重,说因为BigDecimal小数点四舍五入出现问题,导致订单金额偏低,公司损失了十几万美金,而且因为发现的晚,订单都已经发货了,钱要不回来了,造成很大的影响。虽然他朋友是公司老员工,但是发生这么大的事情,也只能引咎辞职了,而且因为个人问题导致公司权益受损,公司有权辞退,并且不进行任何赔偿。

故事带来的教训

我听完这个事情,久久无法回神,对众多小公司而言,因为用户量不高,服务宕机一段时间,其实不会直接造成非常大的影响(滴滴这种独角兽除外),而金额计算错误导致的问题,大多数都是非常致命的错误,目前金额计算一般都采用BigDecimal来进行运算,但是如果BigDecimal不会用或者没用好,也是会造成严重的线上问题。

为了引以为戒,博主特意整理了BigDecimal的易错场景,来培训团队成员,让大家引以为戒,可以用好BigDecimal,计算好金额,保住自己的饭碗。

易错点一:BigDecimal构造参数导致精度丢失问题

BigDecimal decimal = new BigDecimal(0.01);
打印实际值:0.01000000000000000020816681711721685132943093776702880859375
建议使用:BigDecimal.valueOf()方法赋值,比如:
BigDecimal decimal1 = BigDecimal.valueOf(0.01);
同时,如果在高并发或者大量对象创建场景时,也不建议使用new BigDecimal方式创建对象,否则会影响性能,同样推荐BigDecimal.valueOf方式创建对象。

知识点:所以推荐使用BigDecimal.valueOf来赋值,确保金额数据的精度正确。

易错点二:正确使用两个BigDecimal对象的大小比较

num1.equals(num2) 或者 num1.compareTo(num2) 都是比较两个数的大小,但是它们有区别:
equals会先比较值,再比较精度;而compareTo直接比较值,不会比较精度。
BigDecimal decimal2 = new BigDecimal("0.01"); BigDecimal decimal3 = new BigDecimal("0.010"); //false,因为精度不一样 decimal2.equals(decimal3); //true, 只比较数值,不会比较精度 decimal2.compareTo(decimal3)==0;

知识点:所以要根据业务正确选择比较大小方法,确保业务逻辑的正确性。

易错点三:做除法运算时,必须设定精度和选择正确的舍入模式

BigDecimal d1 = BigDecimal.valueOf(1.00); BigDecimal d2 = BigDecimal.valueOf(3.00); BigDecimal d3 = d1.divide(d2);

上述代码执行后,会直接抛出异常:java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
正确写法:
// 精度设置为2位,选择向远离零的方向四舍五入 BigDecimal d3 = d1.divide(d2, 2, RoundingMode.HALF_UP);
BigDecimal舍入模式:

  • RoundingMode.UP:向远离零的方向舍入
  • RoundingMode.DOWN:向靠近零的方向舍入
  • RoundingMode.CEILING:向正无穷方向舍入
  • RoundingMode.FLOOR:向负无穷方向舍入
  • RoundingMode.HALF_UP:向远离零的方向四舍五入
  • RoundingMode.HALF_DOWN:向靠近零的方向四舍五入
  • RoundingMode.HALF_EVEN:银行家舍入法,遵循IEEE 754标准

知识点:所以做除法运算时,务必设定精确位数,避免系统异常崩溃。并且正确理解舍入模式的含义,有助于满足业务的需求。

易错点四:BigDecimal对象一旦设值不可修改原则问题

BigDecimal使用setScale方法设置精度时,原对象不会被修改,需要用新对象去接收。
BigDecimal num = new BigDecimal("1.2345"); // num变量并没有变化,还是4位小数; num.setScale(2, RoundingMode.HALF_UP); // result 才是四舍五入后并保持2位小数点。 BigDecimal result = num.setScale(2, RoundingMode.HALF_UP);

知识点:我们要理解不可变的特性,不要出现理解上的歧义,导致业务出现问题。

复盘反思

BigDecimal只是Java功能中小到不能再小的功能点,但是却有这么多的注意事项。写了这么多年代码之后,我可以明显的感觉到,初级开发和高级开发有着非常明显区别,特别是对待程序严谨性上,经验越多的程序员,可以想到更多的异常场景,从而保证最后的开发质量。

林老师带你学编程知识星球,创始人由工作10年以上的一线大厂人员组成,希望通过我们的分享,帮助大家少走弯路,可以在技术领域不断突破和发展。

具体的加入方式

  • 直接访问链接:https://t.zsxq.com/14F2uGap7
  • “长按”或“扫描”下方二维码噢

星球内容涵盖:Java技术栈、Python、大数据、项目实战、面试指导等主题。

这篇关于被辞退了,因为小数点计算错误的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/544677

相关文章

JavaScript中使用正则判断一个值是否是数字,包含正负,小数点

使用正则表达式来判断: if(/^[+-]?\d*\.?\d*$/.test(str)){//为数字} 实际情况中可以将+去掉,

判断包不包含小数点和有几位小数点

const result = (num.toString()).indexOf('.')if (result !== -1) // 包含小数点num.toString().split('.')[1].length // 小数点位数

职场关系课:辞退下属的行动指南

引言 开人是给团队治病的过程,把病灶祛除,团队才会健康起来。刁难、羞辱、扣钱、不办手续都是蠢办法。为了和不合适的人分手而付出一些经济上的代价,值得。 步骤一:摸清被解约者的底细。 即使你是老板,或者在私企,这一步也很有必要。一个有过硬关系的人无法被简单裁掉,你可能需要和你的领导沟通这件事,让他帮你一起想办法。 步骤二:联系相关部门 确认这个人的用人成本和补偿金,这跟他的服务年限有关。

salesforce 如何不省略公式字段小数点前的0

在 Salesforce 中,公式字段默认会省略小数部分的前导零(例如,将 0.25 显示为 .25)。要显示小数点前的 0,可以手动拼接字符串: 示例公式: IF(Number_Field__c < 1, "0" & TEXT(Number_Field__c), TEXT(Number_Field__c)) 此公式会先检查数字是否小于 1,如果是,则在前面加上 0,确保显示格式为 0.x

带小数点数值的极大次方求解

转自 http://blog.csdn.net/rually/article/details/8585268 http://poj.org/problem?id=1001 原题如下:  Exponentiation Time Limit: 500MS Memory Limit: 10000KTotal Submissions: 113486 Accepted: 27528

Flink SQL因类型错误导致MAX和MIN计算错误

背景 最近在做数据分析,用Flink SQL来做分析工具,因数据源的数据存在不太规范的数据格式,因此我需要通过SQL函数把我需要的数据值从VARCHAR类型的字段中把数据提取出来,然后再做MAX、MIN、SUM这些统计。怎料SUM算出来的结果准确无误,而MAX和MIN算出来的结果却始终不正确,最后发现原来是我用SQL函数提取VARCHAR类型的字段的数据,也是VARCHAR类型,所以导致MAX、

java格式化小数点问题,四舍五入

方法一: 使用DecimalFormat进行数字格式化 public static void test1(DecimalFormat df) {           //默认显示3位小数           double d = 1.5555555;           System.out.println(df.format(d));//1.556           //设置小数点后最大

C++中小数点引用和箭头的区别

首先介绍一下C++中的结构。对于一个结构来说, struct MyStruct { int member_a; }; 如果有个变量MyStruct s,那么使用其中的成员元素时可以用 s.member_a = 1; 如果采用指针方法访问,比如MyStruct * ps,那么同样的访问就必须使用如下形式: (*ps).member_a = 1; 或者 ps->member_a = 1; c++

mysql 存入 小数点后2位的数据 字段类型的设置?

二次开发过程中,有添加金钱额度的字段,所以整理了以下一段: alter table zv_users add column moneys float(8, 2) not null COMMENT '用户拥有的金钱' after integral; 其中moneys float(8, 2)的8代表小数点前8位,2代表小数点后2位; 另有发现decimal或numeric

【Oracle APEX开发小技巧1】转换类型实现显示小数点前的 0 以 及常见类型转换

在 apex 交互式式网格中,有一数值类型为 NUMBER,保留小数点后两位的项,在 展示时小数点前的 0 不显示。 效果如下: 转换前: m.WEIGHT_COEFFICIENT 解决方案: 将 NUMBER(20,2)类型的项转换类型为字符类型 to_char  () to_char(m.WEIGHT_COEFFICIENT,'fm99990.09') 转换后效果