所以,简而言之,
3 √(-8)=( - 8) 1/3
console.log(Math.pow(-8,1/3));
//Should be -2
但是当我测试它时,它会输出
NaN
为什么呢?这是一个错误还是预计会首先出现这种情况?我使用JavaScript绘制图形,但这会弄乱图形。
答案 0 :(得分:17)
您可以使用此代码段进行计算。它也适用于其他权力,例如1/4
,1/5
等
function nthroot(x, n) {
try {
var negate = n % 2 == 1 && x < 0;
if(negate)
x = -x;
var possible = Math.pow(x, 1 / n);
n = Math.pow(possible, n);
if(Math.abs(x - n) < 1 && (x > 0 == n > 0))
return negate ? -possible : possible;
} catch(e){}
}
nthroot(-8, 3);
来源:http://gotochriswest.com/blog/2011/05/06/cube-root-an-beyond/
计算立方根的更快方法:
Math.cbrt = function(x) {
var sign = x === 0 ? 0 : x > 0 ? 1 : -1;
return sign * Math.pow(Math.abs(x), 1 / 3);
}
Math.cbrt(-8);
<强>更新强>
要查找基于整数的立方根,您可以使用受this answer启发的以下函数:
// positive-only cubic root approximation
function cbrt(n)
{
var a = n; // note: this is a non optimized assumption
while (a * a * a > n) {
a = Math.floor((2 * a + (n / (a * a))) / 3);
}
return a;
}
首先假设收敛到a
的最接近的整数a^3 <= n
。可以用相同的方式调整此功能以支持负底座。
答案 1 :(得分:11)
没有错误;你把负数提高到一个分数幂;因此,NaN。
谷歌的最高点来自Dr Math,解释非常好。它表示对于实数(无论如何不是复数),提升到分数幂的负数可能不是实数。最简单的例子可能是-4 ^(1/2)
基本上计算-4的平方根。尽管-8的立方根确实有真正的解决方案,但我认为大多数软件库都发现不进行所有复杂算术更有效,只有当虚部非零时才返回NaN,否则会给你很好的答案。 / p>
修改强>
只是为了清楚地表明NaN
是预期的结果,see the official ECMAScript 5.1 Specification, Section 15.8.2.13。它说:
如果x <0且x是有限的且y是有限的且y不是整数,则结果为NaN。
同样,即使将负数提升到分数幂的一些实例只有一个真正的根,但是对于所有负数到分数根的情况,许多语言只做NaN事件。
请不要认为JavaScript是唯一这样的语言。 C++ does the same thing:
如果x是有限负的且y是有限的但不是整数值,则会导致域错误。
答案 2 :(得分:7)
两个关键问题:
Math
对象(以及大多数其他标准数学库)不会执行负数的分数幂。它在函数接收之前将分数幂转换为浮点数,因此您要求函数计算负数的浮点幂,这可能有也可能没有真正的解。所以它做了务实的事情并且拒绝尝试计算这样的价值。如果你想得到正确的答案,你需要决定你想要的数学校正,并将这些规则写入pow
的非标准实现中。
所有库函数都受到限制,以避免过多的计算时间和不必要的复杂性。
答案 3 :(得分:5)
我喜欢其他答案,但如果覆盖Math.pow
,那么它就可以使用所有第n个负数根:
//keep the original method for proxying
Math.pow_ = Math.pow;
//redefine the method
Math.pow = function(_base, _exponent) {
if (_base < 0) {
if (Math.abs(_exponent) < 1) {
//we're calculating nth root of _base, where n === 1/_exponent
if (1 / _exponent % 2 === 0) {
//nth root of a negative number is imaginary when n is even, we could return
//a string like "123i" but this would completely mess up further computation
return NaN;
}/*else if (1 / _exponent % 2 !== 0)*/
//nth root of a negative number when n is odd
return -Math.pow_(Math.abs(_base), _exponent);
}
}/*else if (_base >=0)*/
//run the original method, nothing will go wrong
return Math.pow_(_base, _exponent);
};
Fiddled有一些测试用例,如果发现错误,请给我一个喊叫声!
答案 4 :(得分:4)
所以我看到一堆围绕Math.pow(...)
的方法很酷,但基于赏金的措辞,我提出的方法略有不同。
有几种计算近似解决根,有些采取比其他更快的步骤。最终停止点达到所需的精度(这取决于你/正在解决的问题)。
我不打算详细解释数学,但是以下是通过目标测试的立方根近似的实现(赏金测试 - 也增加了负范围,因为这个问题标题)。循环中的每次迭代(参见每个方法中的while(Math.abs(xi-xi0)>precision)
循环)都会更接近所需的精度。一旦达到精度,就会对数字应用格式,因此它与从迭代中得到的计算一样精确。
var precision = 0.0000000000001;
function test_cuberoot_fn(fn) {
var tested = 0,
failed = 0;
for (var i = -100; i < 100; i++) {
var root = fn(i*i*i);
if (i !== root) {
console.log(i, root);
failed++;
}
tested++;
}
if (failed) {
console.log("failed %d / %d", failed, tested);
}else{
console.log("Passed test");
}
}
test_cuberoot_fn(newtonMethod);
test_cuberoot_fn(halleysMethod);
牛顿逼近实施
function newtonMethod(cube){
if(cube == 0){//only John Skeet and Chuck Norris
return 0; //can divide by zero, we'll have
} //to settle for check and return
var xi = 1;
var xi0 = -1;
while(Math.abs(xi-xi0)>precision){//precision = 0.0000000000001
xi0=xi;
xi = (1/3)*((cube/(xi*xi))+2*xi);
}
return Number(xi.toPrecision(12));
}
Halley的近似实现 note Halley的近似可以更快地完成求解立方体的步骤,因此它的计算速度比牛顿近似要快。
function halleysMethod(cube){
if(cube == 0){//only John Skeet and Chuck Norris
return 0; //can divide by zero, we'll have
} //to settle for check and return
var xi = 1;
var xi0 = -1;
while(Math.abs(xi-xi0)>precision){//precision = 0.0000000000001
xi0=xi;
xi = xi*((xi*xi*xi + 2*cube)/(2*xi*xi*xi+cube));
}
return Number(xi.toPrecision(12));
}
答案 5 :(得分:3)
它在Chrome控制台中工作
function cubeRoot(number) {
var num = number;
var temp = 1;
var inverse = 1 / 3;
if (num < 0) {
num = -num;
temp = -1;
}
var res = Math.pow(num, inverse);
var acc = res - Math.floor(res);
if (acc <= 0.00001)
res = Math.floor(res);
else if (acc >= 0.99999)
res = Math.ceil(res);
return (temp * res);
}
cubeRoot(-64) // -4
cubeRoot(64) // 4
答案 6 :(得分:1)
//除了符号外,负数的立方根不是正数吗?
Math.cubeRoot= function(n, r){
var sign= (n<0)? -1: 1;
return sign*Math.pow(Math.abs(n), 1/3);
}
Math.cubeRoot(-8)
/* returned value: (Number)
-2
*/
答案 7 :(得分:1)
首先,在ES6中,现在有一个Math.cbrt函数。
在我的Google Chrome测试中,它的工作速度几乎是Math.pow的两倍。有趣的是,我不得不将结果加起来,否则chrome在优化掉功能方面做得更好。
//do a performance test on the cube root function from es6
var start=0, end=0, k=0;
start = performance.now();
k=0;
for (var i=0.0; i<10000000.0; i+=1.0)
{
var j = Math.cbrt(i);
//k+=j;
}
end = performance.now();
console.log("cbrt took:" + (end-start),k);
k=0;
start = performance.now();
for (var i=0.0; i<10000000.0; i+=1.0)
{
var j = Math.pow(i,0.33333333);
//k+=j;
}
end = performance.now();
console.log("pow took:" + (end-start),k);
k=0;
start = performance.now();
for (var i=0.0; i<10000000.0; i+=1.0)
{
var j = Math.cbrt(i);
k+=j;
}
end = performance.now();
console.log("cbrt took:" + (end-start),k);
k=0;
start = performance.now();
for (var i=0.0; i<10000000.0; i+=1.0)
{
var j = Math.pow(i,0.33333333);
k+=j;
}
end = performance.now();
console.log("pow took:" + (end-start),k);
结果:
cbrt took:468.28200000163633 0
pow took:77.21999999921536 0
cbrt took:546.8039999977918 1615825909.5248165
pow took:869.1149999940535 1615825826.7510242
答案 8 :(得分:1)
只想强调在ES6中有一个native cubic root功能。所以你可以这样做(查看支持here)
Math.cbrt(-8)
会返回-2
答案 9 :(得分:0)
这适用于负数和负指数:
function nthRoot(x = 0, r = 1) {
if (x < 0) {
if (r % 2 === 1) return -nthRoot(-x, r)
if (r % 2 === -1) return -1 / nthRoot(-x, -r)
}
return x ** (1 / r)
}
示例:
nthRoot( 16, 2) 4
nthRoot( 16, -2) 0.25
nthRoot(-16, 2) NaN
nthRoot(-16, -2) NaN
nthRoot( 27, 3) 3
nthRoot( 27, -3) 0.3333333333333333
nthRoot(-27, 3) -3
nthRoot(-27, -3) -0.3333333333333333