转自:?http://120183228.iteye.com/blog/1772782
先说清楚为什么要做这个东西。
1 系统在运算浮点数的时候并不一定都准确 java在没出BigDecimal的时候也是一样,运算的时候或多或少0.000000(N个0)1
无论加减乘除都有可能出现 ?甚至一个小数乘以100都有可能出现这种情况
2 flex?
Math.round(n):四舍五入 ?只计算第一位 ?比如0.5 =1 0.45 = 0
Math.floor(n):返回小于或等于指定数字n 的最大整数
Math.ceil(n):返回大于或等于指定数字n 的最小整数
?
原理是通过设置最大保留小数位四舍五入(从最后一位开始四舍五入)截掉小数变整数运算 ?运算完后再加上小数位返回。 测试类里面有使用直接运算和使用BigDecimal.as运算两种方式,有兴趣的朋友多试试几个浮点数运算,很容易出现或多或少0.00000...1的情况。
由于项目中金额哪怕是0.01也有可能后台金额验证出错,也许你判断的时候可以忽略掉0.01的差距,但是从源头解决问题不更好吗?
?
package??
{??
??
????/**??
?????*??准确的计算浮点数?,四舍五入方式是采用最后一位一直到保留小数位的判断。??
?????*?*/??
????public?class?BigDecimal??
????{??
??????????
????????/**??
?????????*?保留小数位??
?????????*?*/??
????????private?var?_maxDecimalLength:int?=?2;??
?????????*?设置保留小数位?如doubleValue有值?设置之后会四舍五入??
????????public?function?set?maxDecimalLength(i:int):void{??
????????????_maxDecimalLength?=?i;??
????????????_doubleValue?=?round(_doubleValue.toString());??
????????}??
????????private?var?_validateStringThrow:Boolean?=?true;??
?????????*?设置验证字符串数据时如不是数字类型是否抛异常??
?????????*?如果不抛异常默认值为0??
????????public?function?set?validateStringThrow(b:Boolean):void{??
????????????_validateStringThrow?=?b;??
????????private?var?_doubleValue:Number?=?0;??
?????????*??设值??
?????????*??@param?value?可以是String、Number、BigDecimal的任意类型??
?????????*??@throws?Error?传入的String类型不是数字??
?????????*??@throws?Error?传入的类型不是String、Number、BigDecimal其中的一个类型??
????????public?function?set?doubleValue(value:*):void{??
????????????_doubleValue?=?getNumber(value);??
??????
????????public?function?get?doubleValue():Number{??
????????????return?_doubleValue;??
?????????*??@param?arg1?保留小数位??
?????????*??@param?arg2?设置验证字符串数据时如不是数字类型是否抛异常,如果不抛异常默认值为0。??
????????public?function?BigDecimal(value:*,arg1:int?=?2,arg2:Boolean?=?true)??
????????{??
????????????_maxDecimalLength?=?arg1;??
????????????_validateStringThrow?=?arg2;??
?????????*???获得String、Number、BigDecimal类型的值??
????????private?function?getNumber(value:*):Number{??
????????????var?_num:Number?=? ????????????if(value?is?String){??
????????????????if(new?Number(value).toString()=="NaN"){??
????????????????????if(_validateStringThrow){??
????????????????????????throw(new?Error("值:"+value+"?不是正确的数字类型!"));??
????????????????????}else{??
????????????????????????_doubleValue?=? ????????????????????}??
????????????????}else{??
????????????????????_num?=?round(value);??
????????????????}??
????????????}else?if(value?is?Number){??
????????????????_num?=?round(value.toString());??
????????????}else?if(value?is?BigDecimal){??
????????????????_num?=?round(value.doubleValue.toString());??
????????????}else{??
????????????????throw(new?Error("BigDecimal不支持此类型的数据:"+value));??
????????????}??
????????????return?_num;??
?????????*??将移除的小数点加上??
?????????*??@throws?_str??可以是String、Number的类型??
?????????*??@throws?_mDL?相乘后应该恢复的是双倍长度的保留小数长度?相除应该是0??加减就是保留小数长度??
????????private?function?getDecimalNumber(_str:*,_mDL:Number?=?NaN):Number{??
????????????var?str:String?=?_str.toString();??
????????????if(_mDL.toString()=="NaN")?_mDL?=?_maxDecimalLength;??
????????????var?_retrunValue:String?=?"";??
????????????if(str.length>_mDL){??
????????????????var?_indexOf:Number?=?str.indexOf(".");??
????????????????if(_indexOf==-1){??
????????????????????_retrunValue?=?str.substring(0,str.length-_mDL)+"."+str.substring(str.length-_mDL,str.length);??
????????????????????str?=?str.replace(".","");??
"."+str.substring(_indexOf-_mDL,250); line-height:18px"> ????????????????_retrunValue?=?"0.";??
????????????????for?(var?i:int?=?0;?i?<_mDL-str.length;?i++)???
????????????????{??
????????????????????_retrunValue?+=?"0";??
????????????????_retrunValue?+=?str;??
????????????return?new?Number(_retrunValue);??
?????????*???将多出的小数点去掉??
?????????*?????
????????private?function?getIntegerNumber(str:*):Number{??
????????????var?_arr:Array?=?str.toString().split(".");??
????????????var?_retrunValue:String?=?_arr[0].toString();??
????????????if(_arr.length> ????????????????_retrunValue?+=?_arr[1].toString();??
????????????????for?(var?i:int?=?_arr[1].toString().length;?i?<?_maxDecimalLength;?i++)???
????????????????for?(var?j:int?=?0;?j?<?_maxDecimalLength;?j++)???
?????????*?四舍五入??
????????private?function?round(value:String):Number{??
????????????var?_arr:Array?=?value.split(".");??
1&&_arr[1].toString().length>_maxDecimalLength){??
????????????????var?_arr0:String?=?_arr[ ????????????????var?_arr1:String?=?_arr[ ????????????????var?_v1:String?=?_arr0+_arr1.substring( ????????????????var?_v2:String?=?_arr1.substring(_maxDecimalLength,_arr1.length);??
????????????????while(true){??
????????????????????if(_v2.length?==? ????????????????????????if(Number(_v2)>4){??
????????????????????????????_v1?=?(new?Number(_v1)+1).toString();??
????????????????????????}??
????????????????????????break;??
????????????????????if(Number(_v2.charAt(_v2.length-1))> ????????????????????????_v2?=?(new?Number(_v2.substring(1))+1))).toString();??
??????????????????????
????????????????return?getDecimalNumber(_v1);??
????????????return?new?Number(value);??
?????????*?相加???
?????????*?@param?value?可以是String、Number、BigDecimal的任意类型??
????????public?function?sum(value:*):Number{??
????????????var?n1:Number?=?getIntegerNumber(doubleValue);??
????????????var?n2:Number?=?getIntegerNumber(getNumber(value));??
????????????_doubleValue?=?getDecimalNumber(n1?+?n2);??
?????????*?相减????
????????public?function?sub(value:*):Number{??
????????????_doubleValue?=?getDecimalNumber(n1?-?n2);??
?????????*?相乘???
????????public?function?mul(value:*):Number{??
????????????_doubleValue?=?round(getDecimalNumber((n1?*?n2),_maxDecimalLength*2).toString());??
?????????*?相除???
????????public?function?div(value:*):Number{??
????????????if(n2==0){??
????????????????_doubleValue?=? ????????????????_doubleValue?=?round(getDecimalNumber((n1?/?n2),0).toString());??
????}??
}??
测试类
<?xml?version="1.0"?encoding="utf-8"?>??
<s:WindowedApplication?xmlns:fx="http://ns.adobe.com/mxml/2009"???
???????????????????????xmlns:s="library://ns.adobe.com/flex/spark"???
???????????????????????xmlns:mx="library://ns.adobe.com/flex/mx">??
????<fx:Script>??
????????<![CDATA[??
????????????import?mx.collections.ArrayCollection;??
????????????import?mx.controls.Alert;??
????????????import?mx.events.FlexEvent;??
??????????????
????????????[Bindable]??
????????????private?var?typeData:ArrayCollection?=?new?ArrayCollection([???
????????????????{"label":"加",?"data":1},???
????????????????{"label":"减",0)">2},250); line-height:18px"> ????????????????{"label":"乘",0)">3},??
????????????????{"label":"除",0)">4}??
????????????]);??
????????????private?var?_result:String?=?"";??
????????????protected?function?button1_clickHandler(event:MouseEvent):void??
????????????{??
????????????????var?b1:BigDecimal?=?new?BigDecimal(t1.text);??
????????????????var?b2:BigDecimal?=?new?BigDecimal(t2.text);??
????????????????if(_type.selectedItem["data"]=="1"){??
????????????????????_result?=?b1.sum(b2).toString();??
????????????????}else?if(_type.selectedItem["data"]=="2"){??
????????????????????_result?=?b1.sub(b2).toString();??
????????????????}else?if(_type.selectedItem["data"]=="3"){??
????????????????????_result?=?b1.mul(b2).toString();??
????????????????}else?if(_type.selectedItem["data"]=="4"){??
????????????????????_result?=?b1.div(b2).toString();??
????????????protected?function?button2_clickHandler(event:MouseEvent):void??
????????????????var?b1:Number?=?new?Number(t1.text);??
????????????????var?b2:Number?=?new?Number(t2.text);??
????????????????????_result?=?(b1+b2).toString();??
????????????????????_result?=(?b1-b2).toString();??
????????????????????_result?=?(b1*b2).toString();??
????????????????????_result?=?(b1/b2).toString();??
????????]]>??
????</fx:Script>??
????<fx:Declarations>??
????????<!--?将非可视元素(例如服务、值对象)放在此处?-->??
????</fx:Declarations>??
????<mx:VBox>??
????????<s:TextInput?id="t1"/>??
????????<s:ComboBox?id="_type"?labelField="label"?dataProvider="{typeData}"?selectedIndex="0"></s:ComboBox>??
????????<s:TextInput?id="t2"/>??
????????<s:Label??text="值:{_result}"/>??
????????<s:Button?id="BigDecimalAccount"?label="使用BigDecimal运算"?click="button1_clickHandler(event)"/>??
????????<s:Button?id="NumberAccount"?label="使用系统直接运算"??click="button2_clickHandler(event)"/>??
????</mx:VBox>??
</s:WindowedApplication>??
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|