如MDN中所述,以下polyfill可用于Math.log10
Math.log10 = Math.log10 || function(x) {
return Math.log(x) / Math.LN10;
};不幸的是,由于浮点运算(在非本机实现中),这:
Math.log10(1000000)将导致:
=> 5.999999999999999绕过这个问题的一种方法是进行一些舍入:
rounding_const = 1000000;
function log10(n) {
return Math.round(rounding_const * Math.log(n) / Math.LN10) / rounding_const;
}有没有更好的方法(算法?)哪一项不会涉及到粗略的舍入?
发布于 2016-06-04 21:19:34
我猜你可以使用你的代码来计算近似值,然后进行二进制搜索,直到你达到所需的值。类似这样的东西(可能还可以改进)
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发布于 2020-06-01 20:46:21
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;
};发布于 2016-06-04 21:04:29
你可以这样做,但我不知道这是否比四舍五入更好。
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
https://stackoverflow.com/questions/37630255
复制相似问题