`
120183228
  • 浏览: 16440 次
  • 性别: 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
分享到:
评论

相关推荐

    大语言模型的低比特计算 戴金权.pdf

    - **计算能力**:高精度的浮点运算需求增加了计算复杂度。 - **显存大小**:存储庞大的模型参数和中间结果需要大量的显存。 - **分布式计算**:为了处理大规模数据集,通常采用分布式训练方法,但这也带来了通信开销...

    友联电子Kinetis K60 Cortex ™-M4核心板开发套件用户手册

    Kinetis K60核心板搭载的是Cortex-M4内核,这是一款高性能、低功耗的32位微控制器,支持浮点运算单元(FPU),具有强大的数字信号处理(DSP)能力,适用于复杂的实时控制和信号处理应用。开发板上的硬件资源包括: - **...

    稳压罐sw16_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    稳压罐sw16_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    基于递推最小二乘法的永磁同步电机参数辨识及其MATLAB仿真

    内容概要:本文详细介绍了利用递推最小二乘法(RLS)进行永磁同步电机参数辨识的方法及其MATLAB仿真过程。首先解释了RLS算法的优势,如不需要概率模型、计算量适中以及适用于嵌入式系统的实时参数更新。接着展示了将电机电压方程转换为标准形式Y=φθ的具体步骤,并提供了核心的RLS迭代代码。文中还讨论了仿真过程中的一些关键技术细节,如遗忘因子的选择、协方差矩阵的初始化和更新方式、电流信号的处理方法等。最终给出了仿真结果,显示电阻和电感的辨识误差分别达到了0.08%和0.12%,并指出了实际应用中需要注意的数据同步和数值稳定性问题。 适合人群:从事电机控制研究的技术人员、研究生及以上学历的学生。 使用场景及目标:①帮助研究人员理解和掌握RLS算法在电机参数辨识中的应用;②提供详细的仿真代码和配置建议,便于快速搭建实验环境;③指导如何优化算法性能,提高参数辨识精度。 其他说明:本文不仅涵盖了理论推导,还包括了大量的实践经验分享和技术细节探讨,有助于读者全面理解RLS算法的实际应用。同时,文中提到的仿真方案可以方便地移植到DSP平台,进一步扩展了其实用价值。

    零起点Python大数据与量化交易

    零起点Python大数据与量化交易

    管道清污机器人sw16可编辑_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    管道清污机器人sw16可编辑_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    电路仿真:数字电路仿真.zip

    电子仿真教程,从基础到精通,每个压缩包15篇教程,每篇教程5000字以上。

    电能质量分析:电压暂降与中断分析.zip

    电子仿真教程,从基础到精通,每个压缩包15篇教程,每篇教程5000字以上。

    thai-scalable-garuda-fonts-0.6.5-1.el8.x64-86.rpm.tar.gz

    1、文件说明: Centos8操作系统thai-scalable-garuda-fonts-0.6.5-1.el8.rpm以及相关依赖,全打包为一个tar.gz压缩包 2、安装指令: #Step1、解压 tar -zxvf thai-scalable-garuda-fonts-0.6.5-1.el8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm

    基于ABAQUS的滑坡与沉降对埋地管道影响的有限元分析及应用

    内容概要:本文详细介绍了利用ABAQUS进行滑坡和沉降对埋地管道影响的有限元分析方法。主要内容涵盖了几何建模、材料属性定义、接触设置、边界条件与加载等方面的技术细节。通过具体的Python脚本示例展示了如何构建模型,并深入探讨了滑坡和沉降条件下管道的应力、应变分布及其潜在破坏机制。此外,还分享了一些实战经验和优化技巧,如材料模型选择、接触条件设置、边界条件处理等,强调了这些因素对结果准确性的重要影响。 适合人群:从事地下管道工程设计、施工及维护的专业技术人员,尤其是那些希望深入了解滑坡和沉降对管道影响的研究人员和技术专家。 使用场景及目标:适用于评估和预测滑坡和沉降对埋地管道造成的力学响应,帮助工程师们更好地理解和应对复杂的地质灾害环境,从而提高管道系统的安全性与稳定性。 其他说明:文中提供的Python代码片段仅为示意,具体实施时需结合ABAQUS的实际接口和项目需求进行适当调整。同时,对于大规模模型的计算,建议使用高性能计算资源以确保效率和精度。

    Java实习一天高频面试突击!最常见的几种面试题型!!!

    Java一天面试突击,迅速掌握Java常见面试题

    莲子去壳机设计模型SW10_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    莲子去壳机设计模型SW10_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    MFRC-522+RC522+RFID射频+IC卡感应模块

    MFRC-522+RC522+RFID射频+IC卡感应模块

    学术研究学术研究提示设计50招:从论文撰写到润色降重的全方位指南学术研究中常见的

    内容概要:《学术研究提示设计 50 招》是一份详尽的指南,旨在帮助研究人员提高学术写作和研究效率。该文档涵盖了从论文撰写、润色、翻译、查重降重、参考文献管理、投稿审稿到文献阅读等多个方面的具体操作指令。每一章节均针对特定任务提供了详细的步骤和注意事项,例如如何撰写标题、摘要、致谢,如何进行英文润色、中英翻译,以及如何优化逻辑结构等。文档还介绍了如何利用AI工具进行文献分析、术语表提取和研究方向探索等内容,为研究者提供了全面的支持。 适合人群:适用于学术研究人员,特别是那些需要撰写、润色和提交学术论文的研究者,包括研究生、博士生及高校教师等。 使用场景及目标:① 提供一系列具体的指令,帮助研究者高效完成论文的各个部分,如撰写标题、摘要、致谢等;② 提供润色和翻译的详细指导,确保论文语言的准确性和专业性;③ 提供查重降重的方法,确保论文的原创性;④ 提供参考文献管理和投稿审稿的指导,帮助研究者顺利发表论文;⑤ 利用AI工具进行文献分析、术语表提取和研究方向探索,提高研究效率。 阅读建议:此资源不仅提供了具体的指令和方法,更重要的是引导研究者如何思考和解决问题。因此,在学习过程中,不仅要关注具体的步骤,还要理解背后的原理和逻辑,结合实际案例进行实践和反思。

    项目optionc-20250409

    项目optionc-20250409

    2023年c语言程序设计基本概念考点归纳.doc

    2023年c语言程序设计基本概念考点归纳.doc

    电能质量仿真:谐波分析与仿真.zip

    电子仿真教程,从基础到精通,每个压缩包15篇教程,每篇教程5000字以上。

    基于Matlab的模拟与数字滤波器设计:IIR、FIR及经典滤波器类型的实战详解

    内容概要:本文详细介绍了使用Matlab进行模拟和数字滤波器设计的方法,涵盖了巴特沃斯、切比雪夫等多种经典滤波器类型。首先讲解了模拟滤波器的设计,如巴特沃斯滤波器的通带平坦性和切比雪夫滤波器的通带波纹特性,并提供了具体的代码示例。接着讨论了数字滤波器的设计,包括IIR滤波器的递归特性和FIR滤波器的线性相位特性,同样附有详细的代码实现。文中还特别强调了不同类型滤波器之间的转换方法以及设计过程中常见的注意事项,如频率归一化、阶数选择等。最后推荐了一些实用的Matlab工具,如fvtool和FDATool,帮助用户更直观地理解和调试滤波器设计。 适合人群:具有一定信号处理基础和技术背景的研究人员、工程师及学生。 使用场景及目标:适用于需要进行滤波器设计的实际工程应用,如通信系统、音频处理等领域。目标是让读者掌握滤波器设计的基本原理和具体实现方法,能够独立完成滤波器的设计和调试。 其他说明:文章不仅提供了理论知识,还通过大量实例代码帮助读者更好地理解和应用所学内容。建议读者在实践中多尝试不同的参数配置,以加深对滤波器特性的理解。

    饲料干燥装置sw16_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    饲料干燥装置sw16_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    MATLAB环境下独立分量分析(ICA)在土木、航空航天、机械领域的振动信号处理应用

    内容概要:本文详细介绍了独立分量分析(ICA)在MATLAB环境下的应用,特别是在土木工程、航空航天和机械领域的振动信号处理方面。文章通过具体实例展示了如何利用ICA将复杂的混合信号分解为独立分量,从而帮助识别结构损伤、故障特征等问题。文中提供了详细的MATLAB代码示例,涵盖数据预处理、核心算法实现以及结果可视化的全过程。此外,还讨论了ICA的应用限制及其与其他信号处理方法的结合使用。 适合人群:从事土木工程、航空航天、机械等领域研究和技术工作的工程师及研究人员,尤其是那些需要处理复杂振动信号的人群。 使用场景及目标:① 土木工程中用于结构健康监测,如桥梁、建筑物的振动数据分析;② 航空航天领域用于飞行器复合载荷分离;③ 机械设备故障诊断,如齿轮箱、轴承等部件的故障特征提取。通过ICA能够有效地从多源混合信号中分离出有用的独立分量,辅助决策。 其他说明:ICA并非适用于所有情况,在某些特定条件下可能会失效,因此需要结合实际情况灵活运用。对于初学者来说,可以从简单的仿真数据入手,逐步过渡到真实的工程项目中。

Global site tag (gtag.js) - Google Analytics