如何克服NaN并继续Javascript中的计算 - 对于sqrt的radicand的负值

Kai*_*ack 8 javascript nan

我已经设置了一个js/three.js程序,用于仅通过两个给定值计算柱面.

当给出体积表面时,唯一的计算非常困难.从这两个值我需要计算半径或高度.

召回公式:

体积V =π·r²·h

表面A = 2·π·r·(r + h)

如果你做数学计算,你将得到立方公式: 0 = r^3 + A/(-2*pi)*r + V/pi

老实说,我无法解决,所以我使用wolframalpha给出半径为r的结果:

r由V和A组成的公式圆柱体

注意:r有三个公式,这是第一个.见wolframalpha.

通过尝试在Javascript中实现这个等式,我意识到radicand ?(54?V^2 - A^3)是负面的并且Javascript正在返回NaN.

这导致了我的问题:我如何克服NaN并继续计算 - 我应该使用复数,如何?你用过什么变通方法?我可以将radicand乘以*(-1),记住这个值,稍后考虑一下吗?

我在这里有点失落,这是我第一次打败NaN :-)

提前感谢您提供的所有提示,建议,解决方案和代码.


编辑(达到目标):生活在这个世界上的人是否可以解决Javascript中的三个方程并且可以发布他的代码?我一般用谷歌搜索"按表面和体积计算圆柱体",似乎没有人在之前做过......

chi*_*NUT 10

因此,丢弃负的radicands并不是最好的解决方案,因为你仍然可能排除有效的实际解决方案,因为第二项中的radicands可以抵消第一项中的虚部.此外,第二和第三根i在他们的公式中,所以你有点被迫在那里处理复数.这些根也应该永远不会被抛弃,因为即使对于具有3个真根的立方体,3个根中的2个仍然使用复数计算!

处理复杂的数字就是这样的

  1. JavaScript本身不处理,和
  2. 是非常重要的,你不想自己实现它.那是在哪里.math.js进来了.

在这里阅读以了解math.js. 但是对于这个问题,你只需要知道一种方法.math.js通过它的math对象完成它的工作,我们关注的方法是math.eval(expr,scope)评估字符串表达式expr并使用中指定的变量赋值scope.

所以,最初看看wolfram提供的3个根:

根

它们有点笨拙.经过仔细检查,他们都有一个共同的术语:

常用术语

该术语的表达AV,所以让我们继续前进,为的函数AV,称为f

F

因此,将该术语替换为我们的新函数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>
Run Code Online (Sandbox Code Playgroud)

在脚本上.首先,定义上述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;
        };
Run Code Online (Sandbox Code Playgroud)

请注意:空格隐含意味着乘以项,即a b=a*b数字的立方根n等效于n^(1/3)

因此,f将评估我们expr使用参数A以及V面积和体积.

现在,我们可以用它来定义将产生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;
        };
Run Code Online (Sandbox Code Playgroud)

所以现在,让我们测试一下.使用您提供的链接中的值,表示半径r2,高度h1.5

然后,体积V=pi*r^2约为18.85,表面积A=2pi*r(r+h)约为43.982.使用上面定义的方法,我们可以得到根源.

请注意,这resultr^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
Run Code Online (Sandbox Code Playgroud)

这与wolfram alpha提供的根源一致. {-3,1.00005,1.99995}

另外请注意,大多数的结果console.log()math.js对象将记录整个对象,这样的:

r1 Complex { re=1.9999528096882697, im=-2.220446049250313e-16, toPolar=function(), more...} 
Run Code Online (Sandbox Code Playgroud)

toString()为了便于阅读,我对我所包含的结果应用了一个.