计算(计算结果保留两位小数数)

金额在运算中应该怎么保留小数位。
Java语言;BigDecimal类;金额运算;
其实这个问题和语言不重要,忽略好了。业务是这样的:
一笔业务先有明细(存在无穷小数的情况,如年费1700,月费就是.6666...67),再所有明细累加算出合计。
我们算的过程是截取3位,141.667,如果5个月,合计就是<span style="font-size:13.7*5=708.335 ,合计显示为708.34.
然后明细列表,明细显示为141.67,<span style="font-size:13.*5=<span style="font-size:13., &708.35和708.34 不一致。
以上就是例子,请教各位银行,保险业各位,你们怎么处理 &实际的明细--显示的明细; 实际的合计--显示的合计之间的小数截取关系的。
我们是程序中计算是四舍五入保留两位小数,建表的时候对字段也会有设置。
我们也有这种除出来无限小数位的情况,比如费用100.00,分3次交,我们会让他第一次交33.33,第二次交33.33,最后一次交33.34,这种会出现尾差的情况,我们是在最后一次处理。
金额一般都是保留两位小数吧,很少见过保留三位的。
--- 共有 4 条评论 ---
100分成"33.33+33.33+33.34"
echo 100 - bcdiv('100', '3', 2) * 2;
: 不是打脸不打脸的问题,别看就是个小数点,100万的0.01就是10000,你的客户承受得起吗?
: 大哥,打人不打脸,日后好相见啊。我突然发现我的代码就有这个问题。这脸火辣辣。。。
非常正确,所有小数处理的时候,这个尾差是最基本的思维能力和逻辑思维能力的检查,我看过无数多程序员,直接round(100/3, 2),就拉到了,几乎每个项目,赔率、金额、成本核算,凡是涉及,我都要一个一个细节去点出。哎。
比如100.33元 数据库存的是10033分前端现实的时候在去转换
--- 共有 1 条评论 ---
其实我的问题更倾向于显示的明细累加和合计值对不上.
我们的做法:开发和业务统一计算口径,先四舍五入还是先计算。
具体用哪种方式差别不大
--- 共有 2 条评论 ---
: 最后结果保留两位啊,但是过程中是不是先四舍五入,要与业务统一口径
遇到金额除不尽的情况,你们用几位小数保留结果?
应该存储和计算统一,比如保留6位或8位,显示统一2位
用aspectj 把所有返回double 类型方法的结果都四舍五入
需求那边给的最终定论是每步结果都四舍五入.
浮点数的精度
看似有穷的小数,在计算机的二进制表示里却是无穷的:
//2884.html
$f = 0.58;
echo intval($f*100); 或者 echo (int)($f*100); //为啥输出57
至于0.58 * 100的具体浮点数乘法,我们不考虑那么细,有兴趣的可以看(Floating point),
我们就模糊的以心算来看 0.58 * 100 = 57.
金融IT领域会涉及到浮点数精度计算,以PHP举例说明.
http://php.net/manual/zh/language.types.float.php
以十进制能够精确表示的有理数如0.1或0.7,无论有多少尾数都不能被内部所使用的二进制精确表示.
因此不能在不丢失一点点精度的情况下转换为二进制的格式.
这就会造成混乱的结果,例如 floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8.
因为该结果内部的表示其实是类似 7.9991118...
永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等.
如果确实需要更高的精度,应该使用bcmath(Binary Calculator Math)函数或者gmp(GNU Multiple Precision)函数.
http://php.net/manual/zh/ref.bc.php
http://php.net/manual/zh/ref.gmp.php
为了保险起见,数据库应该使用字符串来保存大整数,并且采用比如bcmath和gmp这样的数学函数库来进行计算.
http://php.net/manual/zh/language.types.integer.php
比如用PHP对账户余额进行计算时,可以使用bcmath系列任意精度数学计算函数.
乘方 bcpow
开平方根 bcsqrt
比较 bccomp
取模(求余数) bcmod
设置默认精度 bcscale
var_dump((0.5+0.2+0.3)==1); // bool(true)
var_dump((0.5+0.2+0.2+0.1)==1); // bool(false)
echo bccomp('1.01', '1', 1); // 保留1位小数,此时1.01等于1.返回0,表示两个数相等.
echo bccomp('1.01', '1', 2); // 保留2位小数,此时1.01大于1.返回1,表示左边的数比右边大.
PHP处理转账: 用户A给用户B转账10元.
验证用户A输入为正数(abs绝对值等于自身且不为0),最多两位小数(^[0-9]+(.[0-9]{2})$),单笔转账不能超过10000元,并且转账金额小于或等于账户余额.
$transfer = 10;
if ( bccomp($transfer, 10000, 2) == 1 ) {
exit('单笔转账不能超过10000元');
if ($transfer &= $balance_a) {
$balance_a = bcsub($balance_a, $transfer, 2);
$balance_b = bcadd($balance_b, $transfer, 2);
exit('余额不足');
浮点数存在精度的问题,数据库字段采用float和double型都容易产生误差.
如果存储对精度要求比较高的数据,比如账户余额,就不能使用float型了,这时应该使用decimal型.
比如我们将MySQL数据库字段"账户余额"的数据类型定义为decimal(5,2),这样就可以存放-999.99到999.99范围内的数,并且不会出现误差.
括号里左边的数表示总有效位数,右边的数表示小数位数.
如果范围不够用,可以定义为decimal(10,2).trackbacks-0
来考虑这样一种情况,先来看代码:
public&static&void&main(String[]&args){&&&&&&&&System.out.println(<span style="color: #.4&+&<span style="color: #.8);&//&=&1.2&?&&&&&&&&System.out.println(<span style="color: #&-&<span style="color: #.1);&&&&& //&=&0.9&?&&&&&&&&System.out.println(<span style="color: #.2&*&<span style="color: #);& //&=&0.6&?&&&&&&&&System.out.println(<span style="color: #.2&/&<span style="color: #); //&=&0.4&?&&&&}&&&&也许你会天真的认为,第一行打印 1.2,第二行打印 0.9,第三行打印 0.6,第四行打印 0.4,因为依据多年的数学惯性逻辑输出结果与预期的一致是很理所当然的事情嘛!但是当程序跑完之后,输出的结果与预期的大有出入,来看下后台打印的结果:
<span style="color: #.0002<span style="color: #.9999<span style="color: #.0001<span style="color: #.99997&& 结果看到这样的结果,是不是很让人郁闷呢?当然了,这些数据是我故意挑的,并不是所有涉及浮点数的运算操作都会算出这样预期之外的结果,但是一件很明了的事情就是,当操作涉及浮点数运算的时候,我们一定要谨防这样的事情发生。上面代码中,加也好,减也好,乘也好,除也好,它们都是属于 double 级别的运算,那为什么会打印输出这样的结果呢?原因是,并不是所有的浮点数都能够被精确的表示成一个double 类型值,有些浮点数值不能够被精确的表示成 double 类型值,因此它会被表示成与它最接近的 double 类型的值。所以很遗憾,0.4 + 0.8&&# 。&#8230;&#8230;怎么来解决这个问题呢?在 java 中提供了一个 BigDecimal 类来执行精确小数的计算,BigDecimal 类提供了以下操作:算术、标度操作、舍入、比较、哈希算法和格式转换。BigDecimal 类提供的方法:加法:add减法:subtract乘法:multiply除法:divide &&#8230;&#8230; &#8230;&#8230;BigDecimal 类提供的更多的方法请自行查看 API,下面用 BigDecimal 类改写上面的代码实现:
&&&&public&static&void&main(String[]&args){&&&&&&&&System.out.println(new&BigDecimal(<span style="color: #.4).add(new&BigDecimal(<span style="color: #.8)));&&&&&&&& &//&=&1.2&?&&&&&&&&System.out.println(new&BigDecimal(<span style="color: #).subtract(new&BigDecimal(<span style="color: #.1)));&&& //&=&0.9&?&&&&&&&&System.out.println(new&BigDecimal(<span style="color: #.2).multiply(new&BigDecimal(<span style="color: #)));&//&=&0.6&?&&&&&&&&System.out.println(new&BigDecimal(<span style="color: #.2).divide(new&BigDecimal(<span style="color: #)));&&& &//&=&0.4&?&&&&&&&&&&&&}&&&&也许你正在查类 BigDecimal 的 API,API 上对类 BigDecimal 有一大串的文字说明,也许你还没来得及看完,但能够确定的是,类 BigDecimal 确实能够准确保证精确小数的执行,那我上面代码的注释是不是忘记去掉了啊?不是。要是真这么干,那就大祸了。先来看一下后台的打印输出结果:
<span style="color: #.21875<span style="color: #.375<span style="color: #.609375Exception&in&thread "main"&java.lang.ArithmeticException:&Non-terminating&decimal&&no&exact&representable&decimal&result.&&& at&java.math.BigDecimal.divide(BigDecimal.java:1603)&&&&at&example.BigDecimalApp.main(BigDecimalApp.java:20)&&& 如果真这么玩了,你会看到结果更恶心了,这还不算,而且还抛了异常,这是为什么呢?别急,来看一下 API 上是怎么说的:&#8220;
public BigDecimal(double val)&&&&将 double 转换为 BigDecimal,后者是 double 的二进制浮点值准确的十进制表示形式。返回的 BigDecimal 的标度是使 (10scale &#215; val) 为整数的最小值。 注:
1. 此构造方法的结果有一定的不可预知性。有人可能认为在 Java 中写入 new BigDecimal(0.1) 所创建的 BigDecimal 正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于 0.1015625。这是因为 0.1 无法准确地表示为 double (或者说对于该情况,不能表示为任何有限长度的二进制小数)这样,传入 到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。 2. 另一方面,String 构造方法是完全可预知的:写入 new BigDecimal("0.1") 将创建一个 BigDecimal,它正好 等于预期的 0.1。因此,比较而言,通常建议优先使用 String 构造方法3. 当 double 必须用作 BigDecimal 的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用 Double.toString(double) 方法,然后使用 BigDecimal(String) 构造方法,将 double 转换为 String。要获取该结果,请使用 static valueOf(double) 方法。
参数:&&&&val - 要转换为 BigDecimal 的 double 值。 抛出:&&&&&NumberFormatException - 如果 val 为无穷大或 NaN。&#8221;以上文字摘自 API,API 上解释的很清楚了,这里就不多说了,API 建议优先使用 String 构造方法,那我们就来试一下呗:
&&&&public&static&void&main(String[]&args){&&&&&&&&System.out.println(new&BigDecimal("<span style="color: #.4").add(new&BigDecimal("<span style="color: #.8")));&&&&&&& & //&=&1.2&&#8730;&&&&&&&&System.out.println(new&BigDecimal("<span style="color: #").subtract(new&BigDecimal("<span style="color: #.1")));&& &//&=&0.9&&#8730;&&&&&&&&System.out.println(new&BigDecimal("<span style="color: #.2").multiply(new&BigDecimal("<span style="color: #")));&//&=&0.6&&#8730;&&&&&&&&System.out.println(new&BigDecimal("<span style="color: #.2").divide(new&BigDecimal("<span style="color: #")));&&&& //&=&0.4&&#8730;&&&&&&&&&&&&}&&&&后台打印输出结果:
<span style="color: #.2<span style="color: #.9<span style="color: #.6<span style="color: #.4& OK,这下子终于不出篓子了,所以千万不能随随便便使用 BigDecimal(double) 构造器来创建 BigDecimal 对象,因为该构造器是根据它的参数的精确值来创建实例对象的,该构造方法的结果还是有一定的不可预知性,用 BigDecimal(String) 此构造器来创建 BigDecimal 实例那就不会有问题了。以上提到了类&BigDecimal 中的 add 、subtract 、multiply 、divide 方法,在 API 中,你可以看到,这几个方法都各自有自己的一个重载方法,如:add (BigDecimal augend, MathContext mc)& &#8230;&#8230;第二个参数 mc 是什么意思呢?先来看一段代码:
&&&&public&static&void&main(String[]&args){&&&&&&&&//计算结果保留两位有效数字&&&&&&&&System.out.println(new&BigDecimal(Math.PI&+&"").add(new&BigDecimal("<span style="color: #.89842"),new&MathContext(<span style="color: #))); //输出 4.0&&&&&&&&&&&&}&&&&第二个参数 mc 是用来保留计算结果的有效位数的,其他三个方法的重载用法是一样的,这里就不一 一列出来了。 &&
阅读(7947)
随笔分类(8)
随笔档案(104)
积分与排名
阅读排行榜查看: 4410|回复: 2
计算工龄时如何保留两位小数
计算工龄时,我用函数DATEDIF(入职时间,TODAY(),"Y"), 出来的是以年为单位,要是用DATEDIF(入职时间,TODAY(),"M"),计算出来的是月份,若入职,用哪个公式能计算出入职时间是1年2月20天???请教高手
=datedif(,&y&)&&years&&datedif(,&m&)&&months&&datedif(,&d&)&&days&
小妖啊 没看懂啊对函数还是不了解能再讲详细点吗?
Powered by→ SQL SELECT SUM计算的数据保留小数问题【已解决】
&&共有<b style="color:#ff人关注过本帖主题:SQL SELECT SUM计算的数据保留小数问题【已解决】& 知识点 & “计算演练场.(1)得数保留一位小数.2÷...”习题详情
0位同学学习过此题,做题成功率0%
计算演练场.(1)得数保留一位小数.2÷0.9≈12.68÷4.1≈350.6÷42≈(2)得数保留两位小数.4.29÷7≈50÷16≈8.74÷6.2≈ &
本题难度:
题型:解答题&|&来源:网络
分析与解答
习题“计算演练场.(1)得数保留一位小数.2÷0.9≈12.68÷4.1≈350.6÷42≈(2)得数保留两位小数.4.29÷7≈50÷16≈8.74÷6.2≈”的分析与解答如下所示:
根据小数除法的计算法则,直接列竖式计算,再根据要求利用“四舍五入法”求出商的近似数.
解:(1)得数保留一位小数.2÷0.9≈2.212.68÷4.1≈3.1350.6÷42≈8.3(2)得数保留两位小数.4.29÷7≈0.6150÷16≈3.138.74÷6.2≈1.41
找到答案了,赞一个
如发现试题中存在任何错误,请及时纠错告诉我们,谢谢你的支持!
计算演练场.(1)得数保留一位小数.2÷0.9≈12.68÷4.1≈350.6÷42≈(2)得数保留两位小数.4.29÷7≈50÷16≈8.74÷6.2≈...
错误类型:
习题内容残缺不全
习题有文字标点错误
习题内容结构混乱
习题对应知识点不正确
分析解答残缺不全
分析解答有文字标点错误
分析解答结构混乱
习题类型错误
错误详情:
我的名号(最多30个字):
看完解答,记得给个难度评级哦!
经过分析,习题“计算演练场.(1)得数保留一位小数.2÷0.9≈12.68÷4.1≈350.6÷42≈(2)得数保留两位小数.4.29÷7≈50÷16≈8.74÷6.2≈”主要考察你对“4 统计”
等考点的理解。
因为篇幅有限,只列出部分考点,详细请访问。
与“计算演练场.(1)得数保留一位小数.2÷0.9≈12.68÷4.1≈350.6÷42≈(2)得数保留两位小数.4.29÷7≈50÷16≈8.74÷6.2≈”相似的题目:
下面图形中,面积不等于40cm2的是(  )
做一项工作准备用8小时完成,实际只用了5小时,工作效率提高了&&&&%.
直接写得数:6.2+2.8=7.82+2.18=8-3.2=7.7-7=0.09×100=12.76-1.6=0.98-0.09=0+7.5=3.4+4=28÷10=25+75-25+75=÷8=65-17-43=(12.3+7.9)×0=(7.9-7.9)÷5=50-20÷5=&&&&
“计算演练场.(1)得数保留一位小数.2÷...”的最新评论
该知识点好题
该知识点易错题
欢迎来到乐乐题库,查看习题“计算演练场.(1)得数保留一位小数.2÷0.9≈12.68÷4.1≈350.6÷42≈(2)得数保留两位小数.4.29÷7≈50÷16≈8.74÷6.2≈”的答案、考点梳理,并查找与习题“计算演练场.(1)得数保留一位小数.2÷0.9≈12.68÷4.1≈350.6÷42≈(2)得数保留两位小数.4.29÷7≈50÷16≈8.74÷6.2≈”相似的习题。

我要回帖

更多关于 js计算保留两位小数 的文章

 

随机推荐