首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Math.log10 javascript polyfill

Math.log10 javascript polyfill
EN

Stack Overflow用户
提问于 2016-06-04 20:30:48
回答 3查看 533关注 0票数 0

MDN中所述,以下polyfill可用于Math.log10

代码语言:javascript
复制
Math.log10 = Math.log10 || function(x) {
  return Math.log(x) / Math.LN10;
};

不幸的是,由于浮点运算(在非本机实现中),这:

代码语言:javascript
复制
Math.log10(1000000)

将导致:

代码语言:javascript
复制
=> 5.999999999999999

绕过这个问题的一种方法是进行一些舍入:

代码语言:javascript
复制
rounding_const = 1000000;

function log10(n) {
  return Math.round(rounding_const * Math.log(n) / Math.LN10) / rounding_const;
}

有没有更好的方法(算法?)哪一项不会涉及到粗略的舍入?

EN

回答 3

Stack Overflow用户

发布于 2016-06-04 21:19:34

我猜你可以使用你的代码来计算近似值,然后进行二进制搜索,直到你达到所需的值。类似这样的东西(可能还可以改进)

代码语言:javascript
复制
function log(x) {
  var aprox = Math.log(x) / Math.LN10,
      value = Math.pow(10, aprox);
  if(value === x) return aprox;
  if(value < x) {
    var lower = aprox,
        lowerval = value,
        upper = aprox * 1.00000000001,
        upperval = Math.pow(10, upper);
  } else if(value > x) {
    var lower = aprox * .99999999999,
        lowerval = Math.pow(10, lower),
        upper = aprox,
        upperval = value;
  } else {
    return aprox;
  }
  var iterations = 1e3;
  for(var i=0; i<iterations; ++i) {
     var middle = (upper+lower) / 2,
         middleval = Math.pow(10, middle);
    if(middleval < x) {
      lower = middle;
      lowerval = middleval;
    } else if(middleval > x) {
      upper = middle,
      upperval = middleval;
    } else {
      return middle;
    }
  }
  return (upper+lower) / 2;
};
log(1000000); // 6
票数 0
EN

Stack Overflow用户

发布于 2020-06-01 20:46:21

代码语言:javascript
复制
Math.log10 = function (x) {
  if (!(x > 0 && x < 1 / 0)) {
    return Math.log(x) * Math.LOG10E;
  }
  var n = Math.round(Math.log(Math.min(Math.max(x, 10 / Number.MAX_VALUE), Number.MAX_VALUE / 10)) * Math.LOG10E);
  return n + Math.log(x / Math.pow(10, n)) * Math.LOG10E;
};
票数 0
EN

Stack Overflow用户

发布于 2016-06-04 21:04:29

你可以这样做,但我不知道这是否比四舍五入更好。

代码语言:javascript
复制
Math.log10 = Math.log10 || function(value){
  var v = +value, s;
  if(v > 0 && /^(?:10*|0\.0*1)$/.test(s = ""+v)){
    return v < 1? 
      2 - s.length:
      s.length - 1;
  }
  return Math.log(v) / Math.LN10
}

顺便说一句。你的rounding_const可以更高一些。大约1e12到1e14

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37630255

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档