用BigDecimal计算器ee的值,要求使用25位精度

博客分类:
&& 在Java中,使用float可以表示浮点数这是个常识,但是float的精度是有问题的,如果涉及金额,那么一般来说就不能用float类型,而是使用BigDecimal,这是个需要掌握的准则。
Commodities,java(商品类)
public class Commodities{
//商品名称
private St
//商品类型
private St
public int getCommoditiesid() {
public void setCommoditiesid(int commoditiesid) {
moditiesid =
public String getCommoditiesname() {
public void setCommoditiesname(String commoditiesname) {
moditiesname =
public String getCommoditiestype() {
public void setCommoditiestype(String commoditiestype) {
moditiestype =
Commoditiesorder.java(订单类)
public class Commoditiesorder{
//商品数量
//商品金额
public int getOrderid() {
public void setOrderid(int orderid) {
this.orderid =
public int getCommoditiesid() {
public void setCommoditiesid(int commoditiesid) {
moditiesid =
public int getVolume() {
public void setVolume(int volume) {
this.volume =
public float getAmount() {
public void setAmount(float amount) {
this.amount =
以上是两个实体entity,从表示层(JSP)到模型层(Action)的数据传递通过CommoditiesorderAction来实现
CommoditiesorderAction.java类
public class CommoditiesorderAction extends ActionSupport{
//商品数量
//商品金额
//Commoditiesorder实例
private Commoditiesorder commoditiesorder
public int getOrderid() {
public void setOrderid(int orderid) {
this.orderid =
public int getCommoditiesid() {
public void setCommoditiesid(int commoditiesid) {
moditiesid =
public int getVolume() {
public void setVolume(int volume) {
this.volume =
public float getAmount() {
public void setAmount(float amount) {
this.amount =
public Commoditiesorder getCommoditiesorder() {
public void setCommoditiesorder(Commoditiesorder commoditiesorder) {
moditiesorder =
public String execute()throws Exception{
moditiesorder.setOrderid(this.getOrderid());
moditiesorder.setVolume(this.getVolume());
moditiesorder.setAmount(this.getAmount());
return "success";
}
}
在CommoditiesorderAction.java类中,
<moditiesorder.setAmount(this.getAmount())
amount使用了float类型,但是由于amount的含义是金额,那么就设涉及到主体业务中金额的算法,因此需要对amount进行类型转换。
解决方案:将Action中的amount类型改为String,在与Commoditiesorder.java交换值时进行处理
//商品金额
public String getAmount() {
public void setAmount(String amount) {
this.amount =
&&&&&&& }
然后在Action中处理String到BigDecimal类型的转换
&&&&&&& //空值处理
if(this.getAmount().equals("")){
moditiesorder.setAmount(null);
moditiesorder.setAmount(new BigDecimal(this.getAmount()));
}
需要注意的是BigDecimal不支持空值实例化,故要判断空值。另外可以利用Struts提供的
将“空”值转换为null的小技巧,只需在web.xml中设置
&init-param&
&&&& &param-name&convertNull&/param-name&
&&&& &param-value&convertNull&/param-value&
&/init-param&
这样就不需要对空值进行判断了。
浏览 17716
浏览: 230131 次
来自: 南宁
xuexiele ~~
yusl113 写道报错啊it.sauronsoftware. ...
跨平台是个问题。WINDOWS上可以玩玩。
LINUX上不能转码成功的原因是这个包的底层依赖于WINDOW ...
大神帮忙啊命令OK,但是Java代码不行。报错:it.saur ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'使用BigDecimal进行精确运算(实现加减乘除运算)
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了如何使用BigDecimal进行精确运算,最后提供了一个工具类,该工具类提供加,减,乘,除运算
首先我们先来看如下代码示例:
代码如下:public class Test_1 {public static void main(String[] args) {System.out.println(0.06+0.01);System.out.println(1.0-0.42);System.out.println(4.015*100);System.out.println(303.1/1000);}}
运行结果如下0.99999&0.0001&401.94&0.00004
你认为你看错了,但结果却是是这样的。问题在哪里呢?原因在于我们的计算机是二进制的。浮点数没有办法是用二进制进行精确表示。我们的CPU表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。如:2.4的二进制表示并非就是精确的2.4。反而最为接近的二进制表示是 2.9999。浮点数的值实际上是由一个特定的数学公式计算得到的。其实java的float只能用来进行科学计算或工程计算,在大多数的商业计算中,一般采用java.math.BigDecimal类来进行精确计算。在使用BigDecimal类来进行计算的时候,主要分为以下步骤:1、用float或者double变量构建BigDecimal对象。2、通过调用BigDecimal的加,减,乘,除等相应的方法进行算术运算。3、把BigDecimal对象转换成float,double,int等类型。一般来说,可以使用BigDecimal的构造方法或者静态方法的valueOf()方法把基本类型的变量构建成BigDecimal对象。 代码如下:BigDecimal b1 = new BigDecimal(Double.toString(0.48));BigDecimal b2 = BigDecimal.valueOf(0.48);
对于常用的加,减,乘,除,BigDecimal类提供了相应的成员方法。
代码如下:public BigDecimal add(BigDecimal value);//加法public BigDecimal subtract(BigDecimal value); //减法 public BigDecimal multiply(BigDecimal value); //乘法public BigDecimal divide(BigDecimal value); //除法
进行相应的计算后,我们可能需要将BigDecimal对象转换成相应的基本数据类型的变量,可以使用floatValue(),doubleValue()等方法。下面是一个工具类,该工具类提供加,减,乘,除运算。
代码如下:public class Arith {/**&* 提供精确加法计算的add方法&* @param value1 被加数&* @param value2 加数&* @return 两个参数的和&*/public static double add(double value1,double value2){BigDecimal b1 = new BigDecimal(Double.valueOf(value1));BigDecimal b2 = new BigDecimal(Double.valueOf(value2));return b1.add(b2).doubleValue();}
/**&* 提供精确减法运算的sub方法&* @param value1 被减数&* @param value2 减数&* @return 两个参数的差&*/public static double sub(double value1,double value2){BigDecimal b1 = new BigDecimal(Double.valueOf(value1));BigDecimal b2 = new BigDecimal(Double.valueOf(value2));return b1.subtract(b2).doubleValue();}
/**&* 提供精确乘法运算的mul方法&* @param value1 被乘数&* @param value2 乘数&* @return 两个参数的积&*/public static double mul(double value1,double value2){BigDecimal b1 = new BigDecimal(Double.valueOf(value1));BigDecimal b2 = new BigDecimal(Double.valueOf(value2));return b1.multiply(b2).doubleValue();}
/**&* 提供精确的除法运算方法div&* @param value1 被除数&* @param value2 除数&* @param scale 精确范围&* @return 两个参数的商&* @throws IllegalAccessException&*/public static double div(double value1,double value2,int scale) throws IllegalAccessException{//如果精确范围小于0,抛出异常信息if(scale&0){ & throw new IllegalAccessException("精确度不能小于0");}BigDecimal b1 = new BigDecimal(Double.valueOf(value1));BigDecimal b2 = new BigDecimal(Double.valueOf(value2));return b1.divide(b2, scale).doubleValue();}}
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具java.math.BigDecimal.pow(int n)&返回一个BigDecimal,其值是 (thisn), 被精确计算的幂值,使其具有无限精度。
参数n必须在范围0到(包括)。 ZERO.pow(0)返回ONE。
以下是java.math.BigDecimal.pow()方法的声明
public BigDecimal pow(int n)
n&- BigDecimal指数。
此方法返回的BigDecimal对象的n次幂,即值为 thisn
ArithmeticException&- 如果n超出范围
下面的例子显示math.BigDecimal.pow()方法的用法
package com.yiibai;
import java.math.*;
public class BigDecimalDemo {
public static void main(String[] args) {
// create 2 BigDecimal Objects
BigDecimal bg1, bg2;
bg1 = new BigDecimal(&2.17&);
// apply pow method on bg1
bg2 = bg1.pow(3);
String str = &The value of & + bg1 + & to the power of 3 is & + bg2;
// print bg2 value
System.out.println( str );
让我们编译和运行上面的程序,这将产生以下结果:
The value of 2.17 to the power of 3 is 10.218313
加QQ群啦!
JAVA技术群:
MySQL/SQL群:
Python技术群:
大数据开发群: (Java,Python,R,Scala,Hadoop,Spark,zookeeper,kafka等技术)
Web开发群(新群):
(PHP,HTML/HTML5,JS/JQuery,CSS等技术)
Linux技术群(新群): (Redhat/Centos,Ubuntu,Shell,运维,监控等技术)
易百教程移动端:请扫描本页面底部(右侧)二维码关注微信公众号,或直接手机访问:
上一篇:下一篇:4411人阅读
【JAVA】(4)
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作啦!
(一)BigDecimal类的常用的几个构造方法
BigDecimal(int):将int表示形式转换为BigDecimal对象
BigDecimal(String) :将字符串表示形式转换为BigDecimal对象
BigDecimal(double):将double表示形式转换为BigDecimal对象
(二)BigDecimal类的常用方法
add(BigDecimal):BigDecimal对象中的值相加,返回BigDecimal对象
subtract(BigDecimal):BigDecimal对象中的值相减,返回BigDecimal对象
multiply(BigDecimal):BigDecimal对象中的值相乘,返回BigDecimal对象
divide(BigDecimal):BigDecimal对象中的值相除,返回BigDecimal对象
toString():将BigDecimal对象中的值转换成字符串
doubleValue():将BigDecimal对象中的值转换成双精度数
floatValue():将BigDecimal对象中的值转换成单精度数
longValue():将BigDecimal对象中的值转换成长整数
intValue():将BigDecimal对象中的值转换成整数
下面分享一个用于高精确处理常用的数学运算类
package com.per.
import java.math.BigD
* 用于高精确处理常用的数学运算
* Created by lijuan on .
public class ArithmeticUtils {
private static final int DEF_DIV_SCALE = 10;
* 提供精确的加法运算
* v1 被加数
* 两个参数的和
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
* 提供精确的加法运算
* v1 被加数
* 两个参数的和
public static BigDecimal add(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2);
* 提供精确的加法运算
* scale 保留scale 位小数
* 两个参数的和
public static String add(String v1, String v2, int scale) {
if (scale & 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
* 提供精确的减法运算
* v1 被减数
* 两个参数的差
public static double sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
* 提供精确的减法运算。
* v1 被减数
* 两个参数的差
public static BigDecimal sub(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.subtract(b2);
* 提供精确的减法运算
* scale 保留scale 位小数
* 两个参数的差
public static String sub(String v1, String v2, int scale) {
if (scale & 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
* 提供精确的乘法运算
* v1 被乘数
* 两个参数的积
public static double mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
* 提供精确的乘法运算
* v1 被乘数
* 两个参数的积
public static BigDecimal mul(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2);
* 提供精确的乘法运算
* scale 保留scale 位小数
* 两个参数的积
public static double mul(double v1, double v2, int scale) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return round(b1.multiply(b2).doubleValue(), scale);
* 提供精确的乘法运算
* scale 保留scale 位小数
* 两个参数的积
public static String mul(String v1, String v2, int scale) {
if (scale & 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入
* v1 被除数
* 两个参数的商
public static double div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入
* scale 表示表示需要精确到小数点以后几位。
* 两个参数的商
public static double div(double v1, double v2, int scale) {
if (scale & 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入
* scale 表示需要精确到小数点以后几位
* 两个参数的商
public static String div(String v1, String v2, int scale) {
if (scale & 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v1);
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
* 提供精确的小数位四舍五入处理
需要四舍五入的数字
* scale 小数点后保留几位
* 四舍五入后的结果
public static double round(double v, int scale) {
if (scale & 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
BigDecimal b = new BigDecimal(Double.toString(v));
return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
* 提供精确的小数位四舍五入处理
需要四舍五入的数字
* scale 小数点后保留几位
* 四舍五入后的结果
public static String round(String v, int scale) {
if (scale & 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
BigDecimal b = new BigDecimal(v);
return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
* scale 小数点后保留几位
public static String remainder(String v1, String v2, int scale) {
if (scale & 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
BigDecimal
* scale 小数点后保留几位
public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {
if (scale & 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
* 比较大小
* v1 被比较数
* v2 比较数
* 如果v1 大于v2 则 返回true 否则false
public static boolean compare(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
int bj = b1.compareTo(b2);
if (bj & 0)
res = true;
res = false;
好了,本篇文章就这样子啦,存在不对的地方还望指导,感谢^_^
参考文献:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:167592次
积分:2352
积分:2352
排名:第16606名
原创:53篇
评论:134条
文章:38篇
阅读:107108
(4)(1)(1)(1)(5)(7)(1)(5)(1)(7)(4)(4)(8)(7)(2)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'博客分类:
由于计算机是用二进制来存储和处理数字,不能精确表示浮点数,而JavaScript中没有相应的封装类来处理浮点数运算,直接计算会导致运算精度丢失。
为了避免产生精度差异,把需要计算的数字升级(乘以10的n次幂)成计算机能够精确识别的整数,等计算完毕再降级(除以10的n次幂),这是大部分编程语言处理精度差异的通用方法。
关键词:
计算精度 四舍五入 四则运算 精度丢失
1. 疑惑
我们知道,几乎每种编程语言都提供了适合货币计算的类。例如C#提供了decimal,Java提供了BigDecimal,JavaScript提供了Number……
由于之前用decimal和BigDecimal用得很好,没有产生过精度问题,所以一直没有怀疑过JavaScript的Number类型,以为可以直接使用Number类型进行计算。但是直接使用是有问题的。
我们先看看四舍五入的如下代码:
alert(Number(0.009).toFixed(2));
alert(Number(162.295).toFixed(2));
按正常结果,应该分别弹出0.01和162.30。但实际测试结果却是在不同浏览器中得到的是不同的结果:
在ie6、7、8下得到0.00和162.30,第一个数截取不正确;
在firefox中得到0.01和162.29,第二个数截取不正确;
在opera下得到0.01和162.29,第二个数截取不正确
我们再来看看四则运算的代码:
alert(1/3);//弹出: 0.3333
alert(0.1 + 0.2);//弹出: 0.00004
alert(-0.09 - 0.01);//弹出: -0.99999
alert(0.012345 * 0.000001);//弹出: 1.9999e-8
alert(0.000001 / 0.0001);//弹出: 0.999998
按正常结果,除第一行外(因为其本身就不能除尽),其他都应该要得到精确的结果,从弹出的结果我们却发现不是我们想要的正确结果。是因为没有转换成Number类型吗?我们转换成Number后再计算看看:
alert(Number(1)/Number(3));//弹出: 0.3333
alert(Number(0.1) + Number(0.2));//弹出: 0.00004
alert(Number(-0.09) – Number(0.01));//弹出: -0.99999
alert(Number(0.012345) * Number(0.000001));//弹出: 1.9999e-8
alert(Number(0.000001) / Number(0.0001));//弹出: 0.999998
还是一样的结果,看来javascript默认把数字识别为number类型。为了验证这一点,我们用typeof弹出类型看看:
alert(typeof(1));//弹出: number
alert(typeof(1/3));//弹出: number
alert(typeof(-0.));//弹出: number
2. 原因
为什么会产生这种精度丢失的问题呢?是javascript语言的bug吗?
我们回忆一下大学时学过的计算机原理,计算机执行的是二进制算术,当十进制数不能准确转换为二进制数时,这种精度误差就在所难免。
再查查javascript的相关资料,我们知道javascript中的数字都是用浮点数表示的,并规定使用IEEE 754 标准的双精度浮点数表示:
IEEE 754 规定了两种基本浮点格式:单精度和双精度。
  IEEE单精度格式具有24 位有效数字精度(包含符号号),并总共占用32 位。
  IEEE双精度格式具有53 位有效数字精度(包含符号号),并总共占用64 位。
这种结构是一种科学表示法,用符号(正或负)、指数和尾数来表示,底数被确定为2,也就是说是把一个浮点数表示为尾数乘以2的指数次方再加上符号。下面来看一下具体的规格:
&&&&&&& 符号位 &&&&&&& 指数位 &&&&&&& 小数部分 指数偏移量单精度浮点数 1位(31) 8位(30-23) 23位(22-00) 127双精度浮点数 1位(63) 11位(62-52) 52位(51-00) 1023
我们以单精度浮点数来说明:
指数是8位,可表达的范围是0到255
而对应的实际的指数是-127到+128
这里特殊说明,-127和+128这两个数据在IEEE当中是保留的用作多种用途的
-127表示的数字是0
128和其他位数组合表示多种意义,最典型的就是NAN状态。
知道了这些,我们来模拟计算机的进制转换的计算,就找一个简单的0.1+0.2来推演吧(引用自http://blog.csdn.net/xujiaxuliang/archive//5939573.aspx):
十进制0.1
=& 二进制0.10011…(循环0011)
=&尾数为1.00(共52位,除了小数点左边的1),指数为-4(二进制移码为),符号位为0
=& 计算机存储为:0
=& 因为尾数最多52位,所以实际存储的值为0.
而十进制0.2
=& 二进制0.0011…(循环0011)
=&尾数为1.00(共52位,除了小数点左边的1),指数为-3(二进制移码为),符号位为0
=& 存储为:0
因为尾数最多52位,所以实际存储的值为0.
 那么两者相加得:
转换成10进制之后得到:0.00004
从上述的推演过程我们知道,这种误差是难免的,c#的decimal和Java的BigDecimal之所以没有出现精度差异,只是因为在其内部作了相应处理,把这种精度差异给屏蔽掉了,而javascript是一种弱类型的脚本语言,本身并没有对计算精度做相应的处理,这就需要我们另外想办法处理了。
3. 解决办法
3.1 升级降级
从上文我们已经知道,javascript中产生精度差异的原因是计算机无法精确表示浮点数,连自身都不能精确,运算起来就更加得不到精确的结果了。那么怎么让计算机精确认识要计算的数呢?
我们知道十进制的整数和二进制是可以互相进行精确转换的,那么我们把浮点数升级(乘以10的n次幂)成计算机能够精确识别的整数来计算,计算完毕之后再降级(除以10的n次幂),不就得到精确的结果了吗?好,就这么办!
我们知道,Math.pow(10,scale)可以得到10的scale次方,那么就把浮点数直接乘以Math.pow(10,scale)就可以了吗?我最初就是这么想的,但后来却发现一些数字运算后实际结果与我们的猜想并不一致。我们来看看这个简单的运算:
alert(512.06*100);
按常理应该返回51206,但实际结果却是99999。奇怪吧?其实也不奇怪,这是因为浮点数不能精确参与乘法运算,即使这个运算很特殊(只是乘以10的scale次方进行升级)。如此我们就不能直接乘以10的scale次方进行升级,那就让我们自己来挪动小数点吧。
怎么挪动小数点肯定大家是各有妙招,此处附上我写的几个方法:
/**
* 左补齐字符串
* @param nSize
要补齐的长度
* @param ch
要补齐的字符
String.prototype.padLeft = function(nSize, ch)
var len = 0;
var s = this ? this : "";
ch = ch ? ch : '0';// 默认补0
while (len & nSize)
* 右补齐字符串
* @param nSize
要补齐的长度
* @param ch
要补齐的字符
String.prototype.padRight = function(nSize, ch)
var len = 0;
var s = this ? this : "";
ch = ch ? ch : '0';// 默认补0
while (len & nSize)
* 左移小数点位置(用于数学计算,相当于除以Math.pow(10,scale))
* @param scale
要移位的刻度
String.prototype.movePointLeft = function(scale)
var s, s1, s2, ch, ps,
sign = '';
s = this ? this : "";
if (scale &= 0)
ps = s.split('.');
s1 = ps[0] ? ps[0] : "";
s2 = ps[1] ? ps[1] : "";
if (s1.slice(0, 1) == '-')
s1 = s1.slice(1);
sign = '-';
if (s1.length &= scale)
ch = "0.";
s1 = s1.padLeft(scale);
return sign + s1.slice(0, -scale) + ch + s1.slice(-scale) + s2;
* 右移小数点位置(用于数学计算,相当于乘以Math.pow(10,scale))
* @param scale
要移位的刻度
String.prototype.movePointRight = function(scale)
var s, s1, s2, ch,
s = this ? this : "";
if (scale &= 0)
ps = s.split('.');
s1 = ps[0] ? ps[0] : "";
s2 = ps[1] ? ps[1] : "";
if (s2.length &= scale)
s2 = s2.padRight(scale);
return s1 + s2.slice(0, scale) + ch + s2.slice(scale, s2.length);
* 移动小数点位置(用于数学计算,相当于(乘以/除以)Math.pow(10,scale))
* @param scale
要移位的刻度(正数表示向右移;负数表示向左移动;0返回原值)
String.prototype.movePoint = function(scale)
if (scale &= 0)
return this.movePointRight(scale);
return this.movePointLeft(-scale);
}
这样我们升级降级都可以转换成字符串后调用String对象的自定义方法movePoint了,乘以10的scale次方我们传正整数scale,除以10的scale次方我们传负整数-scale。
再来看看我们之前升级512.06的代码,采用自定义方法的调用代码变成这样:
alert(512.06.toString().movePoint(2)); //弹出: 51206
这样直接挪动小数点就不怕它不听话出现一长串数字了(*^__^*)。 当然,movePoint方法得到的结果是字符串,如果要转成Number类型也很方便(怎么转就不再废话了)。
3.2 四舍五入
好,有了升级降级的基础,我们来看看四舍五入的方法,由于不同浏览器对Number的toFixed方法有不同的支持,我们需要用自己的方法去覆盖浏览器的默认实现。
有一个简单的办法是我们自己来判断要截取数据的后一位是否大于等于5,然后进行舍或者入。我们知道Math.ceil方法是取大于等于指定数的最小整数,Math.floor方法是取小于等于指定数的最大整数,于是我们可以利用这两个方法来进行舍入处理,先将要进行舍入的数升级要舍入的位数scale(乘以10的scale次方),进行ceil或floor取整后,再降级要舍入的位数scale(除以10的scale次方)。
代码如下:
Number.prototype.toFixed = function(scale)
var s, s1, s2,
s1 = this + "";
start = s1.indexOf(".");
s = s1.movePoint(scale);
if (start &= 0)
s2 = Number(s1.substr(start + scale + 1, 1));
if (s2 &= 5 && this &= 0 || s2 & 5 && this & 0)
s = Math.ceil(s);
s = Math.floor(s);
return s.toString().movePoint(-scale);
}
覆盖Number类型的toFixed方法后,我们再来执行以下方法
alert(Number(0.009).toFixed(2));//弹出0.01
alert(Number(162.295).toFixed(2));//弹出162.30
在ie6、7、8、firefox、Opera下分别进行验证,都能得到相应的正确的结果。
另一种方式是在网上找到的采用正则表达式来进行四舍五入,代码如下:
Number.prototype.toFixed = function(scale)
var s = this + "";
if (!scale) scale = 0;
if (s.indexOf(".") == -1) s += ".";
s += new Array(scale + 1).join("0");
if (new RegExp("^(-|\\+)?(\\d+(\\.\\d{0," + (scale + 1) + "})?)\\d*$").test(s))
var s = "0" + RegExp.$2, pm = RegExp.$1, a = RegExp.$3.length, b =
if (a == scale + 2)
a = s.match(/\d/g);
if (parseInt(a[a.length - 1]) & 4)
for (var i = a.length - 2; i &= 0; i--)
a[i] = parseInt(a[i]) + 1;
if (a[i] == 10)
b = i != 1;
s = a.join("").replace(new RegExp("(\\d+)(\\d{" + scale + "})\\d$"), "$1.$2");
if (b) s = s.substr(1);
return (pm + s).replace(/\.$/, "");
return this + "";
}
经验证,这两个方法都能够进行准确的四舍五入,那么采用哪个方法好呢?实践出真知,我们写一个简单的方法来验证一下两种方式的性能:
function testRound()
var dt, dtBegin, dtEnd,
dtBegin = new Date();
for (i=0; i&100000; i++)
dt = new Date();
Number("0." + dt.getMilliseconds()).toFixed(2);
dtEnd = new Date();
alert(dtEnd.getTime()-dtBegin.getTime());
}
为了避免对同一个数字进行四舍五入运算有缓存问题,我们取当前毫秒数进行四舍五入。经验证,在同一台机器上运算10万次的情况下,用movePoint方法,平均耗时2500毫秒;用正则表达式方法,平均耗时4000毫秒。
浏览 18634
浏览: 21574 次
来自: 上海
数值太大,导致科学计算,最后运算出错怎么解决
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 复仇之矛e伤害计算 的文章

 

随机推荐