-
Notifications
You must be signed in to change notification settings - Fork 0
50. Pow(x, n) #46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
50. Pow(x, n) #46
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
まあ良いのではないでしょうか。3rdの解法はヘルパー関数用意しなくてもとは思いますが。
- https://discord.com/channels/1084280443945353267/1233603535862628432/1252973832822853642 | ||
- https://github.com/goto-untrapped/Arai60/pull/29 | ||
|
||
再帰は①よりこっちの方がキレイな気がした (現状これで末尾再帰最適化はされないと思うが)。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if n == 0: | ||
return result | ||
if n % 2 == 0: | ||
return self._pow(x * x, n // 2, result) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
n % 2 == 1でearly returnしたり、n & 1で判定したり色々変えてますね。
どれが好みとかあります?
early returnは特別なときにするイメージなので、この上のやつはは個人的にあんまりスッキリしなかったです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
n % 2 == 1 では判定してないですね。nが負のときに言語によって結果が-1になったりして事故の元だなと思いなるべく避けてます。
どれが好みとかあります?
うーん今回はbitが立ってるときに処理するイメージがついたのでbit演算ですかね...
|
||
### ① | ||
|
||
対数オーダーしかスタックに積まれないので再帰で実装。PythonだとC++などと違い値の範囲を気にする場面が減って楽ではある。C++だと n = -2^31 のときに符号を逆にするとsigned intではオーバーフローするのに注意しないといけない。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
同じ処理を書くならループと再帰のどちらが認知負荷が低いかアンケートを取ったところ、ループのほうが認知負荷が低いと答えた人のほうが多かったです。
https://x.com/nodchip/status/1765579286646530148
同じ処理をループと再帰で書ける場合は、チームの平均的なメンバーにとって認知負荷が低い方を選ぶことをお勧めいたします。
class Solution: | ||
def myPow(self, x: float, n: int) -> float: | ||
if n < 0: | ||
return 1 / self.myPow(x, -n) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
n = -n
x = 1 / x
としても良いと思います。
if n == 0: | ||
return 1 | ||
ans = 1 | ||
for i in range(floor(log2(n)) + 1): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
float を使って計算するときに、計算誤差が出ないか不安になりました。計算誤差が出ないことを保証できますか?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
誤差が出ないかというと出るんですが (例: floor(log2(2**63 - 1)) == 63
)、証明じゃなくアレですが多分問題ないと思っています...
まず誤差が大きい側に倒れても n & (1 << i)
でiがnの最上位bitより大きいときは0にしかならないので、余分にループが回るだけで計算結果には影響しないです。なので、 floor(log2(2**x - α))
(α>0で小さい) の値がx-1じゃなくxになる誤差は問題ないです。
問題は floor(log2(2**x + α))
の値がxじゃなくx-1になるような事態が起こるかという話ですが、log2の実装次第 (https://github.com/python/cpython/blob/d66b06107b0104af513f664d9a5763216639018b/Modules/mathmodule.c#L709 を見るとCのlog2を使っている) ではありますが、 x == log2(2**x) <= log2(2**x + α)
になるようには流石に作ってるだろう...という見立てで大丈夫だと判断しました
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IEEE754 の log の仕様見ますかねえ。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://ieeexplore.ieee.org/document/8766229 pdfダウンロードできないです...
ググると落ちてる (見ていいのか分からないですが) んですが、中身見てもあまり分かりませんでした...p.32の 5.3.3 logBFormat operations が怪しいのかな?とは思いましたが...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あ、仕様有料でしたね。llvm とか見てみましょうか。
https://libc.llvm.org/math/log.html
なんかよく分からないですが、これ本当に大丈夫なのか不安になってきました。
しかし、試してみたところ2.0**1023までは大丈夫そうです。
これだけ考えて自信がもてなかったら安全な方に倒すんでしょうかねえ。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
なるほど見るべき箇所参考になります、ありがとうございます。
しかし、試してみたところ2.0**1023までは大丈夫そうです。
倍精度浮動小数点の範囲なら多分大丈夫って感じですかね。
これだけ考えて自信がもてなかったら安全な方に倒すんでしょうかねえ。
そうですね、+1回余分にループ回しておけば良いでしょうからコメント書いてそうするかもです
if n == 0: | ||
return 1 | ||
ans = 1 | ||
for i in range(floor(log2(n)) + 1): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whlie (1 << i) <= n:
として、ループの中で i += 1
しても良いと思います。
https://leetcode.com/problems/powx-n/description/