LoginSignup
0
1

More than 1 year has passed since last update.

pythonエンジニア認定試験受験記⑤

Last updated at Posted at 2021-06-19

前書き

以下のオデッセイ開催の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

・・・なんかものすごく強引な気もするが動けばよかろうなのだ
コードの解説はまた時間がある時に追記しようと思う

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1