前書き
以下のオデッセイ開催のpython基礎認定試験を今度受験するにあたり
勉強して上で学んだことを記事でアウトプットしていく。
Odyssey CBT | オデッセイ コミュニケーションズ
https://cbt.odyssey-com.co.jp
前回で終わりのつもりだったが、その後色々気づいたことが出て来たためおまけとして記載する
四捨五入について
通常四捨五入を行う場合は1~4までを切り捨て、5~9までを切り上げと言うパターンが多いと思う。
というかそれが文字通りの四捨五入だと思っている
pythonで四捨五入を行いたい場合はroundという関数が用意されているためそれを使う
例えば
round(1.543, 1)
とやると1.543を少数第2位(0開始なので1は0,1の二番目)でまとめてねとなる
1.54
ぱっと見問題無いように見えるが次の場合を考える
print(round(1.5, 0))
print(round(2.5, 0))
2.0
上は正しいが下は5を切り上げたいので本来は3と出力したいところだが、どちらも2になっている
これはpythonが偶数側に丸めようとする性質があるかららしい。
つまり1.5であれば偶数側に丸めるので2になるが2.5だと偶数側にまとめるので3にはならず2となってしまうのである
これを解決するにはどうするか調べたところDecimalというモジュールを使うのが良いことがわかった
方法は次の通り
まずdecimalモジュールを読み込みDecimal, ROUND_HALF_UP属性をインポートする
from decimal import Decimal, ROUND_HALF_UP
次にDicimalの引数として文字列型の変換したい数字を入れる
文字列型
を入れるというところがポイントであるintやfloatじゃダメよということである
Decimal('2.5')
これにquantizeというメソッドを使って2つ引数を指定してやる
第一引数はDecimalで揃えたい桁数(今回は少数台1位を切り上げたいので0)を文字列で指定
第二引数は切り上げたいのでrounding=にROUND_HALF_UPという文字列を渡す
因みに以下のリンクにroundingに渡すパラメータにどんなモードがあるか分かりやすく書いてある
https://docs.python.org/ja/3/library/decimal.html#rounding-modes
Decimal('1.5').quantize(Decimal('0'), rounding=ROUND_HALF_UP)
Decimal('2.5').quantize(Decimal('0'), rounding=ROUND_HALF_UP)
Decimal('2')
Decimal('3')
おまけとして以下のような小数点以下の足し算もこのDecimalを使えば意図した結果を出すことができる
なぜ少数同士の足し算で意図した結果にならないかは二進数の問題と丸誤差とか情報処理的な話になるのでここでは割愛する
if 0.3 == 0.1 + 0.1 + 0.1:
print('True')
else:
print('False')
False
Dicimalを使うと次の通り
from decimal import Dicimal
if Decimal('0.3') == Decimal('0.1')+Decimal('0.1')+Decimal('0.1'):
print('True')
else:
print('False')
True
10進数を別の進数に変換
10進数を2進数とか8進数とか16進数に変換するにはどうしたら良いか
答え
bin(),oct(),hex()
を使う
終了!
ではあまりにも味気ないので自分で実装してみたというお話
以下をサンプルにして作っていく
bin(765),oct(765),hex(765)
('0b1011111101', '0o1375', '0x2fd')
できれば引数渡して何進数とか指定して変換してくれる感じがいいよねということで次のようなコードになった
def number_conv(num=255, convert=2):
bin_num = ''
if convert not in (2, 8, 16):
return None
while num != 0:
num, surplus = divmod(num, convert)
bin_num = str(surplus) + bin_num
if convert == 2:
bin_num = '0b'+ bin_num
if convert == 8:
bin_num = '0o'+ bin_num
if convert == 16:
bin_num = '0x' + bin_num
bin_num = bin_num.replace('10','a').replace('11','b').replace('12','c').replace('13','d').replace('14','e').replace('15','f')
return bin_num
print(number_conv(765, 2))
print(number_conv(765, 8))
print(number_conv(765, 16))
0b1011111101
0o1375
0x2fd
・・・なんかものすごく強引な気もするが動けばよかろうなのだ
コードの解説はまた時間がある時に追記しようと思う