javascript 解決默認取整的坑(目前已知的最佳解決方案)

javascript 解決默認取整的坑(目前已知的最佳解決方案)

復現該問題

js在數字操做時總會取更高精度的結果,例如1234/10結果就是123.4,可是在c或者java中整數除以10的結果仍是整數,小數部分被捨去,不只如此 *,%等運算符也會出現這種結果,但咱們有時候更但願捨去取整javascript

使用Math標準庫

Math標準庫提供了Math.floor():向下取整Math.ceil():向上取整Math.round():四捨五入這三種取整方法,效率也不錯,可是在進行一些操做時,總感受彆扭,並且效率會偏低,查看了v8中Math部分的源碼後發現須要進行很是多的操做後才能獲得結果java

//builtins-math-gen.cc文件中聲明瞭math庫的全部方法
// ES6 #sec-math.floor
TF_BUILTIN(MathFloor, MathBuiltinsAssembler) {
  TNode<Context> context = CAST(Parameter(Descriptor::kContext));
  TNode<Object> x = CAST(Parameter(Descriptor::kX));
  MathRoundingOperation(context, x, &CodeStubAssembler::Float64Floor);
}
// code-stub-assembler.cc文件中進行了floor操做
TNode<Float64T> CodeStubAssembler::Float64Floor(SloppyTNode<Float64T> x) {
  if (IsFloat64RoundDownSupported()) {
    return Float64RoundDown(x);
  }
  TNode<Float64T> one = Float64Constant(1.0);
  TNode<Float64T> zero = Float64Constant(0.0);
  TNode<Float64T> two_52 = Float64Constant(4503599627370496.0E0);
  TNode<Float64T> minus_two_52 = Float64Constant(-4503599627370496.0E0);
  VARIABLE(var_x, MachineRepresentation::kFloat64, x);
  Label return_x(this), return_minus_x(this);
  // Check if {x} is greater than zero.
  Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this);
  Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero,
         &if_xnotgreaterthanzero);
  BIND(&if_xgreaterthanzero);
  {
    // Just return {x} unless it's in the range ]0,2^52[.
    GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x);
    // Round positive {x} towards -Infinity.
    var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52));
    GotoIfNot(Float64GreaterThan(var_x.value(), x), &return_x);
    var_x.Bind(Float64Sub(var_x.value(), one));
    Goto(&return_x);
  }
  BIND(&if_xnotgreaterthanzero);
  {
    // Just return {x} unless it's in the range ]-2^52,0[
    GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x);
    GotoIfNot(Float64LessThan(x, zero), &return_x);
    // Round negated {x} towards -Infinity and return the result negated.
    TNode<Float64T> minus_x = Float64Neg(x);
    var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52));
    GotoIfNot(Float64LessThan(var_x.value(), minus_x), &return_minus_x);
    var_x.Bind(Float64Add(var_x.value(), one));
    Goto(&return_minus_x);
  }
  BIND(&return_minus_x);
  var_x.Bind(Float64Neg(var_x.value()));
  Goto(&return_x);
  BIND(&return_x);
  return TNode<Float64T>::UncheckedCast(var_x.value());
}

在進行Math.floor操做時會進行不少操做,複雜度較高,有不少層遞歸才能得到結果less

使用按位運算符

按位運算符中的~是將數字按位取反,位運算是js中計算較快的操做符,把浮點數兩次按位取反後能夠得到捨去取整的結果即Math.floor(5.6)==~~5.6)這是目前已知的最快解決方法
示例代碼函數

/**
 * @param {number} x
 * @return {number}
 */
var reverse = function (x) {
  let ans = 0;
  while (x !== 0) {
    ans = ans * 10 + ~~(x % 10);
    x = ~~(x / 10);
  }
  return (ans >= (2 ** 31) || ans <= -(2 ** 31)) ? 0 : ans;
};

/**
 * @param {number} x
 * @return {number}
 */
var reverse = function (x) {
  let ans = 0;
  while (x !== 0) {
    ans = ans * 10 + Math.floor(x % 10);
    x = Math.floor(x / 10);
  }
  return (ans >= (2 ** 31) || ans <= -(2 ** 31)) ? 0 : ans;
};

以上兩個函數獲取的結果徹底同樣ui

相關文章
相關標籤/搜索