Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions 50. Pow(x, n)/50. Pow(x, n).md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# 50. Pow(x, n)
## STEP1
- 何も見ずに解いてみる
- 繰り返し二乗法を書く。
- 累乗の部分の書き方次第で OverflowError になる。なぜかは不明。

```python
class Solution:
def myPow(self, x: float, n: int) -> float:
if n < 0:
return 1 / self.myPow(x, -n)

result = 1.0
pow = x
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

後の step でコメントありますが、pow だと built-in と被るのと、英単語としても base とかのほうがよいかなと感じました。
https://docs.python.org/ja/3.13/library/functions.html#pow

while n > 0:
if n % 2 == 1:
result *= pow
pow *= pow
# pow **= 2 このようにすると OverflowError
n //= 2
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pow = x としているのであれば、こちら (n) についても、引数をいじっていくよりは exponent のような変数名にしたほうがよさそうです。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x に倣って n も別変数に置き換えるというのは自分も同意です。
一方、引数をいじるということについては、参照渡しではないので問題ないかと思いました。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。おっしゃる通り問題はないのですが読みやすさ的には課題がありますね。

return result
```

## STEP2
### プルリクやドキュメントを参照
- https://docs.python.org/3/library/functions.html#pow
- pow 組み込み関数にあるので変数名は変えた方が良さそう。
- https://github.com/olsen-blue/Arai60/pull/45/files
- 再帰でも書ける。

再帰で書いてみる。
```python
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0:
return 1.0
if n < 0:
return 1.0 / self.myPow(x, -n)

if n % 2 == 1:
return x * self.myPow(x * x, n // 2)
else:
return self.myPow(x * x, n // 2)
```
- // で割っているので (n - 1) // 2 とは書かなくて良いかなと思った。

- https://github.com/TORUS0818/leetcode/pull/47#discussion_r2038337006
- これ読みやすい。n が固定されていて、bit, base という変数名も明確。

これを踏まえて書き直し。
```python
class Solution:
def myPow(self, x: float, n: int) -> float:
if n < 0:
return 1.0 / self.myPow(x, -n)

result = 1.0
bit = 1
base = x
while bit <= n:
if n & bit:
result *= base
base *= base
bit <<= 1
return result
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'# ex) 3^5 = 3^(2^0 + 2^2) = 3^(2^0) * 3^(2^2)'
のようなコメントがあると読み手に優しいかと思いました。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。少なくとも repeated squaring とは書いた方が良さそうですね。

```

- n が負の数の場合 n を正にして再度関数を呼ぶパターンはそんなに読みにくさを感じない。明示的に変換を書いている分数学的に同値な変形がわかりやすいのでは。まあ同一関数内で n, x ともに上書きするのでも全然良いとは思う。

- https://github.com/hroc135/leetcode/pull/43/files
- 上記PRに書いてある IEEE 754 に関する部分を読んだ。NaN の表現などについては知らなかった。
- https://www.geeksforgeeks.org/computer-organization-architecture/ieee-standard-754-floating-point-numbers/

## STEP3
### 3回ミスなく書く
```python
class Solution:
def myPow(self, x: float, n: int) -> float:
if n < 0:
return 1.0 / self.myPow(x, -n)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x=0をケアするとより良いかと思います。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。組み込み関数では以下のようになっていました。
何もエラーの扱いをしないと、ZeroDivisionError: float division by zero が出力されるので、状況がわかるエラー文にしてあげると親切になると思いました。

>> pow(0, -1)
ZeroDivisionError: 0.0 cannot be raised to a negative power

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

組み込み関数でそもそもエラーを出すので特段ケアする必要はないのですね。失礼しました。


result = 1.0
base = x
bit = 1
while bit <= n:
if bit & n:
result *= base
base *= base
bit <<= 1
return result
```

1分,1分,1分で3回Accept