`
120183228
  • 浏览: 16283 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

    博客分类:
  • flex
阅读更多

先说清楚为什么要做这个东西。

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

 

 

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 value 可以是String、Number、BigDecimal的任意类型
		 *  @param arg1 保留小数位
		 *  @param arg2 设置验证字符串数据时如不是数字类型是否抛异常,如果不抛异常默认值为0。
		 *  @throws Error 传入的String类型不是数字
		 *  @throws Error 传入的类型不是String、Number、BigDecimal其中的一个类型
		 * */
		public function BigDecimal(value:*,arg1:int = 2,arg2:Boolean = true)
		{
			_maxDecimalLength = arg1;
			_validateStringThrow = arg2;
			_doubleValue = getNumber(value);
		}
		
		
		/**
		 * 	 获得String、Number、BigDecimal类型的值
		 *  @param value 可以是String、Number、BigDecimal的任意类型
		 *  @throws Error 传入的String类型不是数字
		 *  @throws Error 传入的类型不是String、Number、BigDecimal其中的一个类型
		 * */
		private function getNumber(value:*):Number{
			var _num:Number = 0;
			if(value is String){
				if(new Number(value).toString()=="NaN"){
					if(_validateStringThrow){
						throw(new Error("值:"+value+" 不是正确的数字类型!"));
					}else{
						_doubleValue = 0;
					}
				}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);
				}else{
					str = str.replace(".","");
					_retrunValue = str.substring(0,_indexOf-_mDL)+"."+str.substring(_indexOf-_mDL,str.length);
				}
			}else{
				_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>1){
				_retrunValue += _arr[1].toString();
				for (var i:int = _arr[1].toString().length; i < _maxDecimalLength; i++) 
				{
					_retrunValue += "0";
				}
			}else{
				for (var j:int = 0; j < _maxDecimalLength; j++) 
				{
					_retrunValue += "0";
				}
			}
			return new Number(_retrunValue);
		}

		/**
		 * 四舍五入
		 * */
		private function round(value:String):Number{
			var _arr:Array = value.split(".");
			if(_arr.length>1&&_arr[1].toString().length>_maxDecimalLength){
				var _arr0:String = _arr[0].toString();
				var _arr1:String = _arr[1].toString();
				var _v1:String = _arr0+_arr1.substring(0,_maxDecimalLength);
				var _v2:String = _arr1.substring(_maxDecimalLength,_arr1.length);

				while(true){
					if(_v2.length == 1){
						if(Number(_v2)>4){
							_v1 = (new Number(_v1)+1).toString();
						}
						break;
					}
					if(Number(_v2.charAt(_v2.length-1))>4){
						_v2 = (new Number(_v2.substring(0,_v2.length - 1))+1).toString();
					}else{
						_v2 = (new Number(_v2.substring(0,_v2.length - 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);
			return _doubleValue;
		}
		
		/**
		 * 相减  
		 * @param value 可以是String、Number、BigDecimal的任意类型
		 * */
		public function sub(value:*):Number{
			var n1:Number = getIntegerNumber(doubleValue);
			var n2:Number = getIntegerNumber(getNumber(value));
			_doubleValue = getDecimalNumber(n1 - n2);
			return _doubleValue;
		}
		
		/**
		 * 相乘 
	     * @param value 可以是String、Number、BigDecimal的任意类型
		 * */
		public function mul(value:*):Number{
			var n1:Number = getIntegerNumber(doubleValue);
			var n2:Number = getIntegerNumber(getNumber(value));
			_doubleValue = round(getDecimalNumber((n1 * n2),_maxDecimalLength*2).toString());
			return _doubleValue;
		}
		
		
		/**
		 * 相除 
		 * @param value 可以是String、Number、BigDecimal的任意类型
		 * */
		public function div(value:*):Number{
			var n1:Number = getIntegerNumber(doubleValue);
			var n2:Number = getIntegerNumber(getNumber(value));
			if(n2==0){
				_doubleValue = 0;
			}else{
				_doubleValue = round(getDecimalNumber((n1 / n2),0).toString());
			}
			return _doubleValue;
		}
		
	
	}
}

 

 

 

 

 

测试类

 

 

 

<?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":"减", "data":2}, 
				{"label":"乘", "data":3},
				{"label":"除", "data":4}
			]);
			
			[Bindable]
			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);
				if(_type.selectedItem["data"]=="1"){
					_result = (b1+b2).toString();
				}else if(_type.selectedItem["data"]=="2"){
					_result =( b1-b2).toString();
				}else if(_type.selectedItem["data"]=="3"){
					_result = (b1*b2).toString();
				}else if(_type.selectedItem["data"]=="4"){
					_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>

 

 

 

 

 

最后讨论一个四舍五入的疑问,是先四舍五入再运算还是运算完后四舍五入。

列入 1.064 - 1.055

如果先运算四舍五入保留两位小数  那么就等于1.06 - 1.06 = 0.00

如果运算完后四舍五入保留两位小数  那么就等于 1.064 - 1.055 = 0.009  0.009四舍五入等于0.01

这种时候咋办

 

0
0
分享到:
评论

相关推荐

    用VHDL语言在FPGA上实现浮点运算

    介绍了用VHDL 语言在硬件芯片上实现浮点加/ 减法、浮点乘法运算的方法,并以Altera公司的FLEX10K系列产品为硬件平台, 以Maxplus II 为软件工具,实现了6 点实序列浮点加/ 减法运算和浮点乘法运算

    flex iframe 支持在flash中嵌套入html jsp asp php等

    flex iframe 支持在flash中嵌套入html jsp asp php等flex iframe 支持在flash中嵌套入html jsp asp php等flex iframe 支持在flash中嵌套入html jsp asp php等flex iframe 支持在flash中嵌套入html jsp asp php等flex...

    flex4.5从浅入深第一、二章清晰版

    1. **Flex框架介绍**:Flex是基于ActionScript和MXML的开放源代码框架,用于构建交互式的、基于Web的应用程序。书中可能涵盖了Flex SDK的基本架构,以及它与Flash Player和Adobe AIR的关系。 2. **MXML和...

    基于Flex&amp;Bison;的网页可编程计算器

    《基于Flex&Bison的网页可编程计算器》 在IT领域,构建一个网页可编程计算器是一项常见的实践项目,它能够帮助开发者提升对Web开发和解析器技术的理解。本项目以“基于Flex&Bison的网页可编程计算器”为主题,通过...

    flex C# 基于socket 通讯 应用程序源码

    在本示例中,"flex C# 基于socket 通讯 应用程序源码"描述了一个项目,该项目结合了这两种技术,通过Socket通信实现客户端和服务器端的数据交互。 Socket通信是网络编程的基础,它允许两个网络应用程序之间建立连接...

    ArcGIS Server开发指南基于Flex和.Net源码

    ArcGIS Server开发指南基于Flex和.Net数据随书光盘内容.分两个文件上传。

    电子功用-基于FLEX的高速运算放大器测试电路

    标题中的“电子功用-基于FLEX的高速运算放大器测试电路”揭示了本文档的核心内容,主要探讨的是在电子工程领域中,如何利用FLEX技术对高速运算放大器进行功能测试和性能评估。FLEX(Flexible Logic Element)是一种...

    Flex4基于FluorineFx模块化系统框架

    **Flex4基于FluorineFx模块化系统框架详解** Flex4是Adobe开发的一款用于创建富互联网应用程序(RIA)的框架,它提供了强大的图形和用户界面设计能力,以及高效的客户端和服务器通信机制。FluorineFx是.NET平台上最...

    ArcGIS Server开发指南--基于Flex和.NET源码.part1

    ArcGIS Server开发指南--基于Flex和.NET源码每一部分

    为移动端设计基于Flex的UI框架

    在移动端UI设计中,基于Flex的框架已经成为一种流行的选择,因为它们能够提供高度灵活和响应式的用户界面。本文将深入探讨如何为移动端设计一个基于Flex的UI框架,并着重讲解其核心概念、优势以及如何实现。 Flex,...

    基于flex的地图动态标绘系统

    《基于Flex的地图动态标绘系统详解》 GIS(Geographic Information System)地图系统在现代信息社会中扮演着重要角色,它结合了地理信息与计算机技术,使得数据的可视化和分析更为直观有效。本文将深入探讨一个基于...

    基于Flex的简易图书管理系统(完整版)

    这个“基于Flex的简易图书管理系统(完整版)”是一个使用Flex技术构建的简单图书管理应用程序,它可能包含了实现图书管理功能的各种组件、数据处理逻辑以及用户界面设计。 首先,Flex框架允许开发者创建具有交互性和...

    Flex+Java登录实例完整框架 基于Flex框架

    Flex+Java登录实例完整框架是将 Adobe Flex 与 Java 技术结合,构建的一个功能完善的登录系统。这个框架主要用于创建富互联网应用程序(Rich Internet Applications,RIA),提供丰富的用户体验和强大的后端数据处理...

    基于Flex的 OA管理系统

    **基于Flex的OA管理系统** Flex是一种用于创建富互联网应用程序(RIA)的技术,它基于ActionScript编程语言和Flash Player运行环境。在本项目“基于Flex的OA管理系统”中,开发者使用了Flex 3.0版本来构建一个高效...

    flex 视频聊天 基于red5

    Flex视频聊天基于Red5是一种利用Adobe Flex技术和OpenSource Media Framework (OSMF)的Red5服务器实现的实时视频通信解决方案。Flex是一种开源的编程框架,主要用于构建富互联网应用程序(RIA),而Red5则是一个开放...

    ArcGIS Server开发指南--基于Flex和.NET源码.part2

    ArcGIS Server开发指南--基于Flex和.NET源码第二部分

    Flex 基于Module模块的开发资料完整版

    Flex 基于 Module 模块的开发是一种有效的软件架构策略,它允许将大型应用程序分解为更小、更易于管理的单元,称为模块。模块化的主要目标是提高代码的可维护性、可扩展性和性能。 1. **模块化的定义与原理** - **...

    Flex第一步--基于ActionScript 3.0的Flex 2应用开发 第2、 6、 13章

    Flex是Adobe公司推出的一种用于构建富互联网应用程序(RIA, Rich Internet Applications)的开源框架,它主要基于Flash Player或Adobe AIR运行环境。本资料主要聚焦在Flex 2的应用开发,特别是结合ActionScript 3.0...

    Flex Flex Flex Flex

    Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex ...

    Flex万年历记事本_flex源码

    Flex是Adobe公司推出的一种基于ActionScript 3.0的开源框架,主要用于构建富互联网应用程序(Rich Internet Applications,简称RIA)。这种技术允许开发者创建具有高度交互性和动态视觉效果的Web应用,提供比传统...

Global site tag (gtag.js) - Google Analytics