对浮点数陷阱的几个建议(翻译转贴)

导读:
  use Math.round, or roundToPrecisionlate as possible, and only when you have to. 经可能晚的使用那些截整,是数据发生精度丢失的方法,不在必须的时候不要使用这些方法)
  when doing number comparisons, use the following notClose or fuzzyEqualsinstead of ‘==’ 当进行数值比较的时候,使用notClose 或者fuzzyEquals代替==操作符
  truly think about the degree of precision you need and be consistent. 仔细的考虑精度问题,当必要的时候
  1) Keep things in MVC format, meaning changes percolate down as they are, and views get notified and can reformat on the way up as they need to for themselves without touching the actual model. This is important as floating point math is largely a blackbox like your x-girlfriend. Well behaved at times, and then damn quirky in the next second on something seeming innocuous, making it impossible to predict (and unit test) 保持数据的MVC格式,当数值改变的时候,试图应当得到通知,并且重新格式化次数据。这点很重要,因为浮点数就像你的前女友一样可能是个无底洞。
  Imagine that we are driving a car along the windy highway, and staying in the lanes is the goal to save us from the cliffs of insanity off to either side. Problem is our steering wheel only goes 100% left or 100% right., so for some particular curves it works well, others…lots of thrashing back and forth to stay on the road, in this case the thrashing is the computer trying to fit oddball things like 1/3 into a number system that really only has left or right angle turns.? The first tendency is to try and wrangle say 4.0000001 into 4…as they are close right!? well what happens is by puttting on the brakes (e..g rounding) you introduce another set of steering wheels on the car, hoping that it will cancel it out, when in reality you’ve double the things that can go wrong.


设想我们在一个悬崖上的高速公路上驾驶,唯一一个可以使我们不从两边的悬崖掉下去的方法就是保持我们的行驶路线在车道内。问题是我们的方向盘现在只能打左或者打右。计算机尝试着解决同样的问题,计算机的数值系统通过截整处理1/3和4.00001这样的数据,例如把后者看作是4,圆整相当于是给数值系统添加了一个刹车。
  The computer’s number system is in binary sacrifices precision for speed, it represents numbers (variable and the results of calculationgs) with 16, 32…and 64 bit precision, which is often good enough for most things.? What happens in many calculations is that while a particular number say 1/3 may not display perfectly on screen, that 1/3 * 3? gets us back to a whole number which the computer can represent. So by rounding early, you disrupt this balance, and the computer can never recover the perfect 10 again.


计算机的数值系统使用了二进制牺牲了精度却获得了速度。因此只能获得16位,32位,64位的精度,这通常能够满足我们大部分的需要。。试试看1/3再*3.我们打破了平衡,我们无法回到完美的十进制
  //BAD
  model.num1 = round(someCal(var1, var2));
  if(model.num1 == 0)…do something
  //Better
  model.num1 = someCal(var1, var2);
  if(Math.round(model.num1) == 0)…do something
  2)? When working with a series of these black boxes chained together ( this includes assigning and retrieving from?? displayObject.x, y), it’s like playing the telephone game, where with each person playing, the number of people in the chain passing messages, the more problems that can happen grow. Using the car metaphor say we have 2 steering wheels for the front Left wheel and one for the front Right wheel. Both can go either all the way left or all the way right. We have 4 possibilities, 3 outcomes: 当面对一系列的连在一起的黑盒子的时候。有点像玩电话游戏,每个人玩这个游戏,数据会被传到连着的链,然后通过此传递信息。会发生的问题随之增多,那我们在上一节打的汽车的比方我们有两个方向盘控制前左轮和前右轮,两者可以同时大左也可以打右,因此有三种结果
  L+L=> Left turn
  R+R =>? Right turn
  L+R or R+L => Straight ahead, but hella wobbly.
  Something similar happens at the end of your calculations. You might get left (1) or right (0) or somewhere in the center (0.0001) . The problem with rounding here is that since the output is wobbly it might be 0.0001 or 0.056, or -0.0005 making it impossible to 在计算的最后,有类似的情况,你也许获得最左的值1,或者右边的值0,或者中间的某个值0.0001,但结果可能误差0.0001 0.056 或者-0.0005而不是理想的近似roundToPrecision well. Thus when operating on the output of a calculation, you have to compare against a range of precision, like center is somewhere between both wheels steering L and steering Right. You can think of this also as a Number holding an umbrella, and we are curious if it’s under the umbrella or outside of it. 因此当操纵计算结果的时候,应该要比较值得范围,就像是打左和打右获得中间方向一样。也可以将此看成是打着把伞
  Here is a variant for outside. 这就是外面的变量
  public function notClose(number1:Number, number2:Number, precision:int = 0):Boolean
  {
  var difference:Number = number1 - number2;
  var range:Number = Math.pow(10, -precision);
  trace(-range + ””+ difference + ””+ range);
  var res:Boolean = ( difference <-range??? ) || (? range
  trace(”notClose” + res);
  return res;
  }
  This has two patterns I like. While var res:Object isn’t strictly necessary, it’s possible to return the calc directly,? putting it in this pattern makes it easy to trace ..even if the code is working perfectly fine, when you might be combing through a bunch of calculations looking for how big of an umbrella to make.? The second is
  aligning the ‘<’in the left being lower and right being greater, as they it becomes easier to visualize spatially (for me), like it’s on a number axis. 这是我喜欢的两种泛型,res虽然不是很必要,不是可以直接返回CALC吗?把它放在这个范型里面很容易调试追踪。虽然代码不完美,但是你也许要整合一大堆的计算来看看这个伞有多大。第二个是 <左边的小右边的大,在数轴上很容易就能反应出来>
  3) For some things like working with displayObjects, in the end it has to be rendered to a fixed number of pixels, and especially with text it’s clearer when lines don’t lie on half pixels, creating fuzziness. ?? So while you can calculate in your function down to 0.00000000 etc. in the end it can only be displayed as 0.0, and similarly when expecting 0.0000000 out of your displayObject.x, width etc. you’ll find that it’s far more limited (lookup twips if your interested) 当碰到displayObjects这样的东西的时候,到最后要呈现数个像素,特别是处理到文本的时候,没有线会被放在半像素的地方。即使您能计算到0.00000000的精度,显示的时候精度只有0.0
  This entry was posted on Tuesday, December 4th, 2007 at 4:17 am and is filed under as3, flash, number. You can follow any responses to this entry through the RSS 2.0feed. Responses are currently closed, but you can trackbackfrom your own site.

本文转自
http://troyworks.com/blog/?p=70

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值