加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Flex 准确基于四舍五入的浮点运算

发布时间:2020-12-15 03:54:32 所属栏目:百科 来源:网络整理
导读:转自:?http://120183228.iteye.com/blog/1772782 先说清楚为什么要做这个东西。 1 系统在运算浮点数的时候并不一定都准确 java在没出BigDecimal的时候也是一样,运算的时候或多或少0.000000(N个0)1 无论加减乘除都有可能出现 ?甚至一个小数乘以100都有可能

转自:?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的差距,但是从源头解决问题不更好吗?

?

Flex代码??

收藏代码

  1. BigDecimal.as??

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>??
  • (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

      推荐文章
        热点阅读