質問するログイン新規登録
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1058閲覧

小数点以下を四捨五入して整数にする簡単なコードの正誤

KentaKodama

総合スコア1

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

0クリップ

投稿2023/04/26 10:10

編集2023/04/26 10:14

1

0

こんにちは。シンプルな質問ですが、よろしくお願いします。

プログラミングではよく、小数以下を四捨五入して整数にすることが多いと思います。
例えばPythonでは予め組み込まれたround関数等を使って上手く小数点以下を丸めて整数にすることが一般的です。
自分も簡単に四捨五入できるコードを考えて以下のコードを思い付きました。

python

1x = float(input()) 2print(int(x+0.5))

プログラミングの課題で「小数点以下を四捨五入して整数を出力せよ」という課題があったので上記のコードを提出したら受理されました。しかし、模範解答では以下のように示されていました。

python

1x=float(input()) 2print(int(round(x+0.0005,0)))

果たして自分のコードは正しいのでしょうか?それともどこかに不備があるのでしょうか?単に四捨五入するだけでなく、複雑な計算をした後に四捨五入をする時に問題が生じるかもしれないという懸念もあります。自分のコードにあまり自信が無いので質問してみました。不備のある箇所をご指摘ください。よろしくお願いします。

umimiを押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2023/04/26 10:26

問題をよく確認してみましょう。
hoshi-takanori

2023/04/26 10:36 編集

環境によるかもですが、マイナスの値を入れるとやばいかも…。(そして 0.0005 は謎。)
otn

2023/04/26 11:16

> 十分小さい正数(この場合では 0.0005 など)を加えることで 回避することができます。 なんと、そういうバッドノウハウがあり、そのバッドノウハウを使ったのが模範解答として紹介されていると言うことなのでしょうかね。これはさすがに駄目でしょう。
guest

回答2

0

ベストアンサー

果たして自分のコードは正しいのでしょうか?
正しいと思いますよ。

問題が生じるかもしれないという懸念
たとえば、入力に 3.49999.. と 9を 15こくらい付けてみてください。 4になるはずです。
ただし、これは内部の数値の有効桁数の問題からくるもので、コードの問題ではありません。この場合は数が3.5とみなされてしまうからです。また、数値計算では、整数を2進数で現わすことによる問題もあります。
そういう意味では、コンピュータだからといって計算が正確だとは限らないということは覚えておくといいでしょう。
参考: https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%81%AE%E6%95%B0%E5%80%A4%E8%A1%A8%E7%8F%BE

print(int(round(x+0.0005,0)))
pythonの四捨五入関数のroundは「偶数丸め」なので、たとえば 2.5 は 2 になります。
一般的な四捨五入とは違う結果になります。
このあたりをごまかす(?)ために、ちょっとだけ数を大きくすることで、0.5がかならず切り上げられるようにしているのでしょう。
ただし、こんなことをすると 2.49999 なども 3になってしまいます。まあ、このあたりの精度は先に書いたように厳密ではないので、用途によってはこれで充分ということでしょう。
これが課題だとして、そういう説明をせずにこの模範回答を出すのは不親切だと思いますね。

投稿2023/04/26 11:09

TakaiY

総合スコア14545

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KentaKodama

2023/04/26 11:49

ありがとうございます。実用上は問題無さそうですが、とても細かい計算をする時はこういう単純なコードでは全て上手く行くわけではないんですね。
TakaiY

2023/04/26 12:01

別回答の質問に > 正確な問題文は小数第3位まであらわされた正実数を四捨五入せよ とありますね。 であれば、模範回答はまったく正しいです。 少数台3位までの数であれば、 第4位に5を足しても通常の結果に影響は出ず、x.5の偶数丸めの影響もキャンセルすることができますね。 ということで、模範回答は問題の回答としてはまったく正しいということにあります。 当然、質問者さんの回答もまったく正しい回答となります。
guest

0

1つめのコードでは、そのまま四捨五入していますが、2つ目のコードでは0.0005を足してから四捨五入しているので、それらは異なる処理です。質問の見間違いか、模範解答の見間違いかでしょう。

0.0005を足さないと、概ね同じなので、その前提で回答を続けます。
int(x+0.5)int(round(x,0))の違いは2点あり、
・前者は、xが負の数の時に四捨五入にならない(負の場合は0.5を足すのでなく引くのが正しい。もちろん問題の前提で正しか無いのであればOKです)
・負だと前者が間違っているので、正の範囲だけで考えることにしても、小数点以下がちょうど0.5の時に、前者は切り上げるが、後者は偶数側に向かって丸める(0.5は0に、1.5は2に)

2点目はどちらが正しいと言うことではないのですが、
例えば、四捨五入してから平均を取ることを考えます。
元データが全ての実数値を取りえる場合は、あまり影響は無いと思いますが、
元データが、例えば0.1の倍数しか取らない場合、四捨五入してから平均を取ると、
元データのままで平均を取るのに比べると前者の場合はすこし多い側にずれます。

[0.0,0.1,0.2,...,99.9,100.0] のような0.1刻みの数についてやってみましょう。

ということで、この仕様の丸めが使われることが多いようです。
(Rubyのroundだとちょうど0.5の時にどうするかを指定できるのですが)

投稿2023/04/26 11:08

otn

総合スコア86367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2023/04/26 11:43 編集

> 質問の見間違いか、模範解答の見間違いかでしょう。 質問のコメントに書きましたが、模範解答が間違っているというのは想定外でした。 0.5を常に(絶対値が大きくなる方向に)切り上げる丸めなら、正解は、int( x+0.5 if x>=0 else x-0.5) でしょうか。
KentaKodama

2023/04/26 11:51

正確な問題文は小数第3位まであらわされた正実数を四捨五入せよというものです。ただ、この模範解答を見ても何のためにこのような細かい数を足すのか分からなかったので質問してみました。とても参考になるご意見ありがとうございました。
otn

2023/04/26 14:06 編集

>正確な問題文は小数第3位まであらわされた正実数を四捨五入せよというものです。 そういう前提があれば、間違ったコードでは無いですね。 ただ、「模範解答」と言ってしまうのは問題あると思いますが。 「解答例」とかじゃなくて「模範解答」で間違いないですかね? 正の数であるという前提が付いていたのなら、質問者さんの解答がより模範的な解答です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問