因此,丢弃负基数并不是最好的解决方案,因为您仍然可能排除有效的实数解决方案,因为第二项中的基数可能会抵消第一项中的虚部。此外,第二和第三根的公式中有 i,所以你不得不在那里处理复数。这些根也不应该被丢弃,因为即使对于具有 3 个实根的三次方,3 个根中的 2 个仍然是使用复数计算的!
处理复数是
- JavaScript 无法原生处理,并且
- 足够重要,以至于您不想自己实现它。那就是那里。 math.js 进来了。
阅读 here 以了解 math.js。但是对于这个问题,您只需要了解一种方法即可。 math.js 通过它的math 对象完成它的工作,我们关心的方法是math.eval(expr,scope),它将评估字符串表达式expr 并使用scope 中指定的变量赋值。
因此,首先查看 wolfram 提供的 3 个根:
它们有点笨拙。仔细观察,它们都有一个共同的术语:
该术语是A 和V 的表达式,因此我们将其移至A 和V 的函数,称为f
所以用这个词代替我们的新函数f,现在根更易于管理:
那么,让我们开始吧。您只需在项目顶部包含math.js:
<script type="text/javascript" language="JavaScript"
src="http://cdnjs.cloudflare.com/ajax/libs/mathjs/0.26.0/math.min.js"></script>
进入脚本。首先,定义上述f函数:
var f = function(A, V) {
var scope = {A: A, V: V};
var expr = math.eval(
'(sqrt(6) pi^(3/2) sqrt(54 pi V^2-A^3)-18 pi^2 V)^(1/3)'
,scope);
return expr;
};
请注意:空格隐含意味着相乘,即a b=a*b,并且数字n的立方根等于n^(1/3)
所以f 将使用参数A 和V 来评估我们的expr 面积和体积。
现在我们可以使用它来定义将生成 3 个根的函数,r1、r2 和 r3,给定任何面积 A 和体积 V
var r1 = function(A, V) {
var scope = {A: A, V: V, f: f(A, V)};
var expr = math.eval(
'A/(6^(1/3) f)+f/(6^(2/3) pi)'
, scope);
return expr;
};
var r2 = function(A, V) {
var scope = {A: A, V: V, f: f(A, V)};
var expr = math.eval(
'-((1+i sqrt(3)) A)/(2*6^(1/3) f) - ((1-i sqrt(3)) f)/(2*6^(2/3) pi)'
, scope);
return expr;
};
var r3 = function(A, V) {
var scope = {A: A, V: V, f: f(A, V)};
var expr = math.eval(
'-((1-i sqrt(3)) A)/(2*6^(1/3) f) - ((1+i sqrt(3)) f)/(2*6^(2/3) pi)'
, scope);
return expr;
};
现在,让我们测试一下。使用您提供的link 中的值,假设半径r 是2,高度h 是1.5
那么,体积V=pi*r^2 约为18.85,表面积A=2pi*r(r+h) 约为43.982。使用上面定义的方法,我们可以得到根。
请注意,result 是使用给定根计算r^3 + A/(-2*pi)*r + V/pi 的结果,因此如果结果是0,则根计算正确。由于舍入误差,实际值将精确到约 15 位数。
var A, V, r, scope;
A = 43.982, V = 18.85;
//test r1
r = r1(A, V);
scope = {A: A, V: V, r: r};
console.log('r1', r, 'result: ',math.eval('r^3+A/(-2pi) r+V/pi', scope));
//r1 1.9999528096882697 - 2.220446049250313e-16i result: 4.440892098500626e-15 - 1.1101077869995534e-15i
//round to 5 decimals:
console.log('rounded r1:', math.round(r,5), 'rounded result: ',math.round(math.eval('r^3+A/(-2pi) r+V/pi', scope),5));
//rounded r1:1.99995 rounded result: 0
//test r2
r = r2(A, V);
scope = {A: A, V: V, r: r};
console.log('r2', r,'result: ', math.eval('r^3+A/(-2pi) r+V/pi', scope));
//r2 -2.9999999737884457 - 1.6653345369377348e-16i result: 2.6645352591003757e-15 - 8.753912513083332e-15i
//round to 5 decimals:
console.log('rounded r2:', math.round(r,5),'rounded result: ', math.round(math.eval('r^3+A/(-2pi) r+V/pi', scope),5));
//rounded r2: -3 rounded result: 0
//test r3
r = r3(A, V);
scope = {A: A, V: V, r: r};
console.log('r3', r, 'result: ',math.eval('r^3+A/(-2pi) r+V/pi', scope));
//r3 1.000047164100176 + 4.440892098500626e-16i result: -1.7762101637478832e-15i
//round to 5 decimals
console.log('rounded r3:', math.round(r,5), 'rounded result: ',math.round(math.eval('r^3+A/(-2pi) r+V/pi', scope),5));
//rounded r3: 1.00005 rounded result: 0
这与wolfram alpha 提供的根源一致。
{-3,1.00005,1.99995}
还要注意math.js 对象中console.log() 的大部分结果都会记录整个对象,如下所示:
r1 Complex { re=1.9999528096882697, im=-2.220446049250313e-16, toPolar=function(), more...}
为了便于阅读,我将toString() 应用于我包含的结果。