Ada 中的二次方程
我刚刚过来并决定尝试一些艾达。 缺点是语法和函数与 C++ 相差甚远。 所以我必须喜欢塞进各种东西才能让这个东西发挥作用。
我的问题是,是否有更好的方法来进行这种计算,我在这里所做的
IF(B < 0.0) THEN
B := ABS(B);
X1 := (B / 2.0) + Sqrt( (B / 2.0) ** 2.0 + ABS(C));
X2 := (B / 2.0) - Sqrt( (B / 2.0) ** 2.0 + ABS(C));
ELSE
X1 := -(B / 2.0) + Sqrt( (B / 2.0) ** 2.0 - C);
X2 := -(B / 2.0) - Sqrt( (B / 2.0) ** 2.0 - C);
END IF;
我在负数方面遇到了一些问题,这就是为什么我做了一个 IF 语句并使用 ABS() 将它们变成正数。但奇怪的是,它对于另一种情况却非常有效,这很奇怪......
I just came around and decided to try some Ada.
The downside is that the syntax and function strays quite away from C++.
So I had to like cram various stuff to get this thing to work.
My question is if there are some better way to do this calculation that what I have done here
IF(B < 0.0) THEN
B := ABS(B);
X1 := (B / 2.0) + Sqrt( (B / 2.0) ** 2.0 + ABS(C));
X2 := (B / 2.0) - Sqrt( (B / 2.0) ** 2.0 + ABS(C));
ELSE
X1 := -(B / 2.0) + Sqrt( (B / 2.0) ** 2.0 - C);
X2 := -(B / 2.0) - Sqrt( (B / 2.0) ** 2.0 - C);
END IF;
I had some problem with negative numbers, that's why I did a IF statement and used ABS() to turn those into positive. But the weird thing is that it works perfectly for the other case, which is strange...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
二次公式为
x = ( -b +/- sqrt ( b ** 2 - 4*a*c ) ) / ( 2 * a )
我猜 a 是 1。
所以
x = -( b/2 ) +/- sqrt ( ( ( b ** 2 ) / 4 ) - c )
计算
d = ( b ** 2 ) * 0.25 - c
然后检查其标志。如果
d
的符号为负,则有复数根;按照您的意愿处理它们。如果
b
恰好为负,则用+abs ( c )
替换- c
会产生垃圾。通常乘以 0.5 或 0.25 比除以 2.0 或 4.0 更好。
The quadratic formula is
x = ( -b +/- sqrt ( b ** 2 - 4*a*c ) ) / ( 2 * a )
I'm guessing a is 1.
so
x = -( b/2 ) +/- sqrt ( ( ( b ** 2 ) / 4 ) - c )
Calculate
d = ( b ** 2 ) * 0.25 - c
then check its sign.If the sign of
d
is negative you have complex roots; handle them as you wish.Replacing
- c
with+ abs ( c )
ifb
happens to be negative will give you rubbish.Usually multiplying by 0.5 or 0.25 is better than dividing by 2.0 or 4.0.
虽然我不了解 Ada,但我看到以下可以优化的内容:
IF
指令的第一个分支中,您已经知道B
为负。因此,您可以说B := -B
而不是B := ABS(B)
。或者更好:只需在第一个分支中使用B
的地方使用-B
即可。B/2.0
四次。将B/2.0
分配给辅助变量B_2
可能会更有效(也更清晰)(或者在以下情况下再次将其分配给B
):你不想花费另一个变量)并使用它。sqrt
也被计算两次。将其分配给辅助变量可以节省运行时间(并让读者清楚地知道完全相同的子表达式被使用了两次)。B_2*B_2
而不是**2.0
可能会更快;更好的是使用专用的平方函数(如果 Ada 中有的话)。Though I don't know Ada, I see following things that can be optimized:
IF
instructiuon you already know thatB
is negative. So you can sayB := -B
instead ofB := ABS(B)
. Or better: just use-B
where you usedB
in the first branch.B/2.0
four times. It could be more efficient (and also more clear) to assignB/2.0
to an auxilary variableB_2
(or assign it toB
again if you don't want to spend another variable) and use it instead.Also the
sqrt
is calculated twice. Assigning it to an auxilariy variable saves runtime (and makes it explicite for the reader that exactly the same subexpresion is used twice).B_2*B_2
instead of**2.0
; even better would be to use a dedicated square function, if there is one in Ada.对我来说,这个问题更多地与数值算法相关,而不是与 Ada 语言相关。
与数值计算一样,人们必须经常(如果不是总是)参考参考/学术论文。
这些类似的问题总是让我想起这一点:
https://en.wikipedia.org/wiki/Fast_inverse_square_root
你只能找到以下技巧如果你“做数学”或找到一些可以解决你的问题的论文。
PS:正如 wikiepdia 文章指出的那样,这种实现对于大多数平台来说可能已经过时了
To me, the question is more related to numeric algorithm than to Ada language.
As always with numeric computing, one must often (if not -always-) refer to reference/academic papers.
These kinda questions always reminds me of this :
https://en.wikipedia.org/wiki/Fast_inverse_square_root
You can only find the following tricks if you "do the maths" or find some paper that adresses your issue.
PS: as the wikiepdia article points out, this implementation is probably obsolete for most platforms now
求解二次方程并不像大多数人想象的那么简单。
求解 ax^2 + bx + c = 0 的标准公式是,
但是当
4 ac << b^2
,计算x1
涉及减去接近的数字,并且会使您失去准确性,因此您使用以下方法来代替,这会产生更好的x1,但其x2与x1有相同的问题多于。
因此,计算根的正确方法是
使用 x1 = q / a 和 x2 = c / q,我发现这非常有效。如果你想处理 delta 为负或复系数的情况,那么你必须使用复杂的算术(这也很难得到正确的结果)。
编辑:使用 Ada 代码:
Solving quadratic equations is not as simple as most people think.
The standard formula for solving
a x^2 + b x + c = 0
isbut when
4 a c << b^2
, computingx1
involves subtracting close numbers, and makes you lose accuracy, so you use the following insteadwhich yields a better x1, but whose x2 has the same problem as x1 had above.
The correct way to compute the roots is therefore
and use
x1 = q / a
andx2 = c / q
, which I find very efficient. If you want to handle the case whendelta
is negative, or complex coefficients, then you must use complex arithmetic (which is quite tricky to get right too).Edit: With Ada code:
给定 ax2 + bx + c = 0 二次公式给出 x = (-b +/- sqrt(b2-4ac) ) / 2a 的解。判别式 d = b2-4ac 对于实值根为正值,对于具有非零虚部(即非实复数)的根为负值,并且当根为一个双根。
因此,Ada 代码如下:
注意:我对 Ada 有点生疏,但这应该接近正确的语法。
Given ax2 + bx + c = 0 the quadradic formula gives solutions for x = (-b +/- sqrt(b2-4ac) ) / 2a. The discriminant d = b2-4ac will be positive for real valued roots, negative for roots with a non-zero imaginary component (i.e. a non-real complex number) and will be 0 when the root is a double root.
So, the Ada code for this would be:
Note: I'm a bit rusty in Ada, but this should be close to the proper syntax.