私は平方根を近似する関数を書こうとしていて(数学モジュールがあることはわかっています...自分で実行したいのですが)、浮動小数点演算に夢中になってしまいました。どうすればそれを回避できますか?
_def sqrt(num):
root = 0.0
while root * root < num:
root += 0.01
return root
_
これを使用すると、次のような結果になります。
_>>> sqrt(4)
2.0000000000000013
>>> sqrt(9)
3.00999999999998
_
round()
を使用するだけで十分だと思いますが、これを本当に正確にできるようにしたいと思っています。 6桁または7桁まで計算できるようにしたい。私が丸めている場合、それは不可能です。 Pythonで浮動小数点計算を適切に処理する方法を理解したいと思います。
Python-ハードウェアの2進浮動小数点演算を使用するどの言語でも同じ動作が見られます。最初に ドキュメントを読んでください 。
それを読んだ後は、コードに100分の1を追加しているではないことをよりよく理解できます。これはまさにあなたが追加しているものです:
>>> from decimal import Decimal
>>> Decimal(.01)
Decimal('0.01000000000000000020816681711721685132943093776702880859375')
その文字列は、バイナリ浮動(Cの「倍精度」)の正確な10進値を、正確な10進値0.01に示します。実際に追加しているのは、1/100より少し大きいサイズです。
浮動小数点数値エラーの制御は「数値解析」と呼ばれるフィールドであり、非常に大きく複雑なトピックです。浮動小数点数が10進数値の単なる近似であるという事実に驚かされている限り、decimal
モジュールを使用してください。それはあなたにとって「浅い」問題の世界を取り除くでしょう。たとえば、関数に次の小さな変更を加えたとします。
from decimal import Decimal as D
def sqrt(num):
root = D(0)
while root * root < num:
root += D("0.01")
return root
次に:
>>> sqrt(4)
Decimal('2.00')
>>> sqrt(9)
Decimal('3.00')
正確ではありませんが、100分の1を正確に追加しているため、単純な例ではそれほど驚くことではありません。
別の方法は、フロートに固執し、isバイナリフロートとして正確に表現できるものを追加することです:I/2**J
形式の値。たとえば、0.01を追加する代わりに、0.125(1/8)または0.0625(1/16)を追加します。
次に、平方根を計算するための「ニュートン法」を調べます;-)