【参考】
- Cardano のメソッドを使用した 3 次方程式の解法入門
- Cardano による解決法
- カルダノメソッドパッケージをダウンロードする
- x^3+1=0 の解法問題、3次方程式逆関数問題
- Micorsoft-Math-solver Microsoft Math Tool
- WolframAlpha: 逆関数/逆関数
- Baidu 百科事典 - 3 次方程式の根を求める公式
【問題の説明】
1 つの変数で 3 次方程式を解く
1 つの変数で 3 次方程式を解きます:
ax 3 + bx 2 + cx + d = 0 ax^3+bx^2+cx+d=0× _3+bx _2+cx _+d=0
これを解決するには多くの方法がありますが、Cardano メソッドによって得られる解決策は次のとおりです。
単項 3 次多項式: y = f ( x ) = ax 3 + bx 2 + cx + dy=f(x)=ax^3+bx^2+cx+dy=f ( x )=× _3+bx _2+cx _+d =>ax 3 + bx 2 + cx + d − y = 0 ax^3+bx^2+cx+dy=0× _3+bx _2+cx _+d−y=0
【コード】
既製のパッケージ Cardano_method
- Python パッケージを使用できます: install
cardano_method
[ここを参照]
このパッケージの使用法:pip install cardano_method
CubicEquation
最初のパラメーター リストに対応する関数は次のとおりです。[a, b, c, d]
これは、方程式の係数を解くことです。
しかし、問題が見つかりました。方程式x 3 + 1 = 0 x^3+1=0を解きます。バツ3+1=0の場合、エラー レポートの分母は 0: ですfrom cardano_method.cubic import CubicEquation a = CubicEquation([1, 3, 4, 4]) print(a.answers) # j表示虚部后缀 # [(-2+0j), (-0.5+1.322875j), (-0.5-1.322875j)] print(a.answers[0].real) # 获取第一个解的实部 print(a.answers[0].imag) # 获取第一个解的虚部
ZeroDivisionError
。a = CubicEquation([1, 0, 0, 1])
しかし実際には、x 3 + 1 = 0 x^3+1=0バツ3+1=0の解は次のとおりです:x 1 = − 1 x_1=-1バツ1=− 1 ,x 2 = 1 2 + 3 2 i x_2=\frac{1}{2}+\frac{\sqrt{3}}{2}iバツ2=21+23i ,x 3 = 1 2 − 3 2 i x_3=\frac{1}{2}-\frac{\sqrt{3}}{2}iバツ3=21−23i(这里 i i iは虚数を表します。)パッケージのバグを解決する方法を詳しく知りたいですか?
計算式に従って解決策のコードを書きます
-
解関数は、解に対応する式に従って記述できます。 [注: 浮動小数点計算について質問がありますか? 】
def cardano_solution_v0(a, b, c, d): ab = -b/float(3*a) q = (3*a*c-(b**2)) / (9*(a**2)) r = (9*a*b*c-27*(a**2)*d-2*(b**3)) / (54*(a**3)) delta_sqrt = (q**3+r**2)**(1.0/2) s = (r+delta_sqrt)**(1.0/3) t = (r-delta_sqrt)**(1.0/3) imag = complex(0, (s-t)*(3**(1.0/3))/2) x1 = s+t+ab x2 = -(s+t)/2+ab+imag x3 = -(s+t)/2+ab-imag return x1, x2, x3
テストの変更では浮動小数点が保持されていますが、まだ問題があります。
cardano_method
パッケージの結果と一致していますか? ? ? [注:どちらにcardano_solution_v0
もcardano_solution_v1
問題がありますが、正しい解決策については、次の関数を参照してください。cardano_solution
】def round_ri(xo, n=4): xr, xi = round(xo.real, n), round(xo.imag, n) if xi == 0: return xr else: return complex(xr, xi) def cardano_solution_v1(a, b, c, d): ab = -b/float(3*a) q = (3*a*c-(b**2)) / (9*(a**2)) r = (9*a*b*c-27*(a**2)*d-2*(b**3)) / (54*(a**3)) delta_sqrt = round((q**3+r**2)**(1.0/2), 4) # print("r, delta_sqrt:", r, delta_sqrt, round(r-delta_sqrt, 4)) s = round((r+delta_sqrt)**(1.0/3), 8) t = round(r-delta_sqrt, 4)**(1.0/3) print("st,ab:", s, t, ab) imag = complex(0, (s-t)*(3**(1.0/3))/2) x1 = s+t+ab x2 = -(s+t)/2+ab+imag x3 = -(s+t)/2+ab-imag return round_ri(x1), round_ri(x2), round_ri(x3)
式そのものが間違っているのでしょうか?それとも浮動小数点/基数の問題でしょうか? もう一度確認する必要があります。。。
-
他の数式をテストする: Baidu Encyclopedia - 単項 3 次方程式の根を求める公式
これは、1 次元 3 次方程式の係数が複素数の場合、カルダノの公式に問題があり (何が問題なのか?)、次の一般的な根を求める公式が使用されることを意味します。
def cardano_solution(a, b, c, d): #u = round((9*a*b*c-27*(a**2)*d-2*(b**3)) / (54*(a**3)), 4) #v = round(3*(4*a*c**3 - b**2*c**2-18*a*b*c*d+27*a**2*d**2+4*b**3*d) / (18**2*a**4), 4) ** (1.0/2) u = (9*a*b*c-27*(a**2)*d-2*(b**3)) / (54*(a**3)) v = (3*(4*a*c**3 - b**2*c**2-18*a*b*c*d+27*a**2*d**2+4*b**3*d) / (18**2*a**4)) ** (1.0/2) if abs(u+v) >= abs(u-v): m = (u+v) ** (1.0/3) else: m = (u-v) ** (1.0/3) if m == 0: n == 0 else: n = (b**2-3*a*c) / (9*a**2*m) # w = complex(0, -0.5+(3/4)**(1.0/2)) # w2 = complex(0, -0.5-(3/4)**(1.0/2)) w = -0.5+(-3/4)**(1.0/2) w2 = -0.5-(-3/4)**(1.0/2) ab = -b/float(3*a) x1 = m+n+ab x2 = w*m+w2*n+ab x3 = w2*m+w*n+ab # return x1, x2, x3 return round_ri(x1), round_ri(x2), round_ri(x3)
テスト結果
cardano_solution
とcardano_method
パッケージを照合し、x 3 + 1 = 0 x^3+1=0を解くことができます。バツ3+1=0問題ありません:print(cardano_solution(1,3,4,4)) print(cardano_solution(1,0,0,-1)) print(cardano_solution(1,0,0,1)) # ((-0.5+1.3229j), -2.0, (-0.5-1.3229j)) # (1.0, (-0.5+0.866j), (-0.5-0.866j)) # ((0.5+0.866j), -1.0, (0.5-0.866j)) print(CubicEquation([1,3,4,4]).answers) print(CubicEquation([1,0,0,-1]).answers) print(CubicEquation([1,0,0,1]).answers) # 报错 # [(-2+0j), (-0.5+1.322875j), (-0.5-1.322875j)] # [(1+0j), (-0.5+0.866025j), (-0.5-0.866025j)] # ZeroDivisionError ...
【まとめ】
- 公式に従って自分で書いた関数は
cardano_solution
単項三次方程式を解くことができます。 - ダウンロードしたパッケージ
cardano_method
と、Cardano 式を使用して直接記述された関数に問題があります。なぜなら?
P.S. Python は複素数の実数部と虚数部を取得します。接尾辞を使用してj
虚数を表します。たとえばa+bj
、middlea
は実数部であり、b
虚数部は Python でcomplex(a,b)
複素数を生成するために使用されます。
x = 2+1.5j
print(x.real) # 打印实部:2
print(x.imag) # 打印虚部:2
x1 = complex(2,1.5) # 使用`complex`生成复数 2+1.5j