我正在做Codewars challenge,我必须使用参数a,b和amp;创建一个函数。 c对应于二次方程ax ^ 2 + bx + c = 0并求解x。目标不仅是解决x,还要尽可能减少花费的Math.sqrt调用次数。 (您还必须返回具有唯一解决方案的数组)。
我想出了一个解决方案:
function solveQuadratic(a, b, c) {
if ((4*a*c > b*b) || ((a === 0) && (b === 0))) { return undefined;}
else if (a === 0) {return [-c/b];}
else {
var xVals = [];
var sqrt = Math.sqrt(b*b - 4*a*c);
xVals.push((-b - sqrt)/2*a);
xVals.push((-b + sqrt)/2*a);
if (xVals[0] === xVals[1]) {xVals.pop();}
return xVals;
}
}
我收到了错误消息:
您使用6个Math.sqrt调用传递了测试。 您应该能够通过4次或更少次Math.sqrt调用传递这些测试。
我认为将表达式的平方根部分的结果存储在变量(sqrt)中会阻止它被多次调用以评估表达式并为变量赋值。但事实并非如此。
所以我有几个问题:
答案 0 :(得分:3)
添加c
为零时的案例:
....
var sqrt = c==0?Math.abs(b):Math.sqrt(b*b - 4*a*c);
....
<强> [编辑] 强>
此外,要通过所有测试,您的解决方案在分割时需要括号:
xVals.push((-b - sqrt)/(2*a));
xVals.push((-b + sqrt)/(2*a));
答案 1 :(得分:2)
一种简单的方法是使用memoization。使用闭包来保留使用的静态值列表,这样就不会为已经计算的值调用Math.sqrt
var cachingSqrt = (function() {
var inputs = {};
return function(val) {
if (inputs.hasOwnProperty(val)) {
return inputs[val];
} else {
return inputs[val] = Math.sqrt(val);
}
}
})();
这个过程的概括将是
function createCachedResults(fn, scope) {
var inputs = {};
return function(val) {
if (inputs.hasOwnProperty(val)) {
return inputs[val];
} else {
return inputs[val] = fn.call(scope, val);
}
}
}
cachingSqrt = createCachedResults(Math.sqrt, Math);
你可以像
一样使用它var cachingSquareRoot = createCachedResults(Math.sqrt, Math);
function solveQuadratic(a, b, c) {
if ((4*a*c > b*b) || ((a === 0) && (b === 0))) {
return undefined;
}
else if (a === 0) {
return [-c/b];
} else {
var xVals = [];
var sqrt = cachingSquareRoot(b*b - 4*a*c);
xVals.push((-b - sqrt)/2*a);
xVals.push((-b + sqrt)/2*a);
if (xVals[0] === xVals[1]) {
xVals.pop();
}
return xVals;
}
}
答案 2 :(得分:2)
关键是在Math.sqrt(x)
和x === 0
时避免x === b^2
,因为答案已经知道。这两种情况发生在b^2 === 4ac
和4ac === 0
时,因此代码需要将这两种情况短路以避免额外的Math.sqrt()
次调用。
所以,所有特殊情况都是:
b^2 - 4ac < 0
或a === 0 && b === 0
回答undefined
。a === 0
时(在这种情况下,等式是线性的,而不是二次的)所以答案是-c / b
。c === 0
4ac === 0
-b / a
只有0
和b^2 - 4ac === 0
。-b / (2 * a)
在哪种情况下答案只是Math.sqrt()
结合使用Ruud的建议和Joanvo建议的固定版本,它只会传递4个function solveQuadratic(a, b, c) {
var delta = (b * b) - (4 * a * c), sqrt;
if ((delta < 0) || ((a === 0) && (b === 0))) {
return undefined;
} else if (a === 0) {
return [-c / b];
} else if (c === 0) {
return b === 0 ? [0] : [-b / a, 0];
} else if (delta == 0) {
return [-b / (2 * a)];
} else {
sqrt = Math.sqrt(delta);
return [(-b - sqrt) / (2 * a), (-b + sqrt) / (2 * a)];
}
}
来电:
Math.sqrt()
这是一个基于上述版本的版本,并添加了Juan的答案中的缓存。在初始标准测试中,仅报告一次function solveQuadratic(a, b, c) {
var delta = (b * b) - (4 * a * c), sqrt;
if ((delta < 0) || ((a === 0) && (b === 0))) {
return undefined;
} else if (a === 0) {
return [-c / b];
} else if (c === 0) {
return b === 0 ? [0] : [-b / a, 0];
} else if (delta == 0) {
return [-b / (2 * a)];
} else {
sqrt = sqrt2(delta);
return [(-b - sqrt) / (2 * a), (-b + sqrt) / (2 * a)];
}
}
var sqrt2 = (function() {
var cache = {0:0, 1:1, 4:2, 9:3};
return function(x) {
if (cache.hasOwnProperty(x)) {
return cache[x];
} else {
var result = Math.sqrt(x);
cache[x] = result;
return result;
}
}
})();
操作。
{{1}}
答案 3 :(得分:1)
您应该为discriminant为零的情况添加快捷方式。
...
else if (b*b == 4*a*c) return [-b / (2*a)];
...