0

我在动作脚本中有一个数字,通过一些任意数学得出:

var value:Number = 45 * (1 - (1 /3));
trace(value);//30.00000000004

现在,我想取这个数字的上限,除非它大于下一个较低整数的量小于某个 epsilon。在上面的例子中,我真的想四舍五入到 30,但只有在我知道我得到一个舍入错误的情况下:

Math.ceil(value); //I want 30, but get 31
Math.ceil(30.1);  //In this case, it's reasonable to get 31

有没有一种优雅的方法来截断 actionscript 中的数字?或者轻松丢弃小于某个 epsilon 的数字的任何部分?

4

3 回答 3

2

这种方法对你有帮助吗?

var precision:int = 4;
var isActualCeilingValRequred:Boolean;
var thresholdValForCeiling:int = 100;

private function getCeilingValue(num:Number):Number
{
  var tempNum = num * Math.pow(10, precision);
  var decimalVal = tempNum % Math.pow(10, precision);

  if(decimalVal < thresholdValForCeiling) {
    return Math.floor(num);
  } else {
    return Math.Ceil(num);
  }
}
于 2012-06-07T14:28:29.270 回答
1
var value:Number = 45 * (1 - (1 /3));
trace(value);//30.00000000004

// Play with arbitraryPrecision until you are satisfied with
// the accuracy of your results
var arbitraryPrecision:int = 3;
var fixed:Number = value.toFixed(arbitraryPrecision);

trace(Math.ceil(fixed));
于 2012-06-07T00:40:53.507 回答
0

将数字四舍五入到指定小数位数的基本方法是将数字乘以 10^DIGITS 将小数点 DIGITS 数字左移,执行四舍五入,然后除以相同的 10^DIGITS 以移动小数指向右边。

var value:Number = 45 * (1 - (1 / 3));
trace(value); // 30.000000000000004
trace(Math.ceil(value)); // 31
// Round the number to 13 decimal digits.
const POWER:Number = 1e13;
value = Math.round(value * POWER) / POWER;
trace(value); // 30
// Compute number's ceiling.
value = Math.ceil(value);
trace(value); // 30`

它适用于您的示例,但有一个很大的问题。如果您将值更改为450 * (1 - (1 / 3));,您的原始问题将再次出现。现在要摆脱它,您必须四舍五入到 12 位十进制数字。基本上,双精度格式(数字)的有效位可以容纳大约 15 个有效数字。这意味着随着值增加十倍,小数点向左移动,并且您要删除的最后一个“4”位越来越接近小数点。所以代码变得更加复杂。

var value:Number = 450 * (1 - (1 / 3));
trace(value); // 30.000000000000004
trace(Math.ceil(value)); // 31
var exp:Number = Math.floor(Math.log(Math.abs(value)) * Math.LOG10E);
trace('exp=' + exp); // exp=2
const POWER:Number = Math.pow(10, 14 - exp);
value *= POWER;
trace(value); // 300000000000000.06
value = Math.round(value);
trace(value); // 300000000000000
value /= POWER;
trace(value); // 300

如您所见,无论值的大小如何,它现在都可以工作。首先,我通过取数字绝对值的以 10 为底的对数,然后将其向下舍入来找到数字的指数。如果计算a = value * Math.pow(10, exp);,则值可以表示为 a * 10^b,其中 (1 ≤ |a| < 10),称为归一化科学记数法。但这不是我们在这里所做的。现在我们知道小数点左边有多少位,我们将小数点向右移动,但不要太远,以保持一个 0 和我们想要去掉的这个错误数字,在右边小数点。因此,乘以 10^(14-exp),四舍五入,然后除以相同的幂。

于 2015-06-22T17:24:01.103 回答