質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.47%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

6回答

1759閲覧

小数点の計算で期待した結果が返ってこない

Kentaro0919

総合スコア258

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2019/05/16 00:21

編集2019/05/16 01:39

小数点の計算で期待値とちがう結果になってしまいどのように修正すればいいか
困っています

今のコード

python

1from math import ceil 2 3ceil(0.07 * 100 ) / 100 40.08

-> 期待値は0.07なのですが0.08 となってしまします。

小数点第2位まで表示して、それ以下は切り上げを行いたいのですが
どのように修正すればいいですか

python

1 2float(Decimal(0.079).quantize(Decimal('.00'))) 3

とすると良さそうなのですが 合っているか確認する方法はありますか

期待値は

python

1def test_95_per_5_Mbps_007(): 2 assert get_kakin(0.07) == 0.07 3 4def test_95_per_5_Mbps_0070(): 5 assert get_kakin(0.070) == 0.07 6 7def test_95_per_5_Mbps_0071(): 8 assert get_kakin(0.071) == 0.08 9 10def test_95_per_5_Mbps_0072(): 11 assert get_kakin(0.072) == 0.08 12 13def test_95_per_5_Mbps_0075(): 14 assert get_kakin(0.075) == 0.08 15 16def test_95_per_5_Mbps_0076(): 17 assert get_kakin(0.076) == 0.08 18 19def test_95_per_5_Mbps_0079(): 20 assert get_kakin(0.079) == 0.08

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

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

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

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

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

cateye

2019/05/16 00:40

実行してみればいいのでは?
Kentaro0919

2019/05/16 00:47 編集

もちろん実行はしています バグを修正したいので どのように検証 テストをすればいいかも含めて知りたいのです。 >>> float(Decimal(0.071).quantize(Decimal('.00'))) 0.07 >>> float(Decimal(0.079).quantize(Decimal('.00'))) 0.08
quickquip

2019/05/16 01:29

であれば最後の一文をそのように直すべきでは。この欄で返答するのではなくて質問に反映させるべきです。
can110

2019/05/16 01:30

「小数点第2位まで表示して、それ以下は切り上げを行いたい」というのがよく分かりません。 いくつか具体的な数値の変換例をあげてもらえないでしょうか? (たとえば0.07001, 0.0701, 0.0704, 0.0705の結果など)
cateye

2019/05/16 02:02 編集

切り上げというのは。少数以下が0でない場合、整数に1加算して小数部を破棄するという事だと思いますが?・・・違いますか? もしそうなら、最初の答えで合っているのでは?
guest

回答6

0

変換仕様がよく分かりませんが、私なら以下のように組みます。
意図(仕様)としては

  • 小数点以下第4位を四捨五入することにより、それ以下の桁は無視する→0.070001などは0.07になるように
  • その結果に対して切り上げを行う。

としています。
また、テストにおいても小数点以下第3位以降も値を含むことを考慮したケースも用意するようにします。

バグを修正したいので どのように検証 テストをすればいいかも含めて知りたいのです。

についてですが、まずは変換仕様とそれとセットになるテストケースを明確に決定すべきかと思います。
コーディングはそのあとです。

Python

1def func(val): 2 ret = Decimal(str(val)) 3 ret = ret.quantize(Decimal('.000'), ROUND_HALF_UP) # 小数第4位を四捨五入 4 ret = ret.quantize(Decimal('.00'), ROUND_UP) # 小数第3位を切り上げ 5 return ret 6 7for val in [0.07, 0.07001, 0.0701, 0.0704, 0.0705, 0.071]: 8 ret = func(val) 9 print('{} -> {}'.format(val, func(val))) 10 11""" 120.07 -> 0.07 130.07001 -> 0.07 140.0701 -> 0.07 150.0704 -> 0.07 160.0705 -> 0.08 170.071 -> 0.08 18"""

投稿2019/05/16 02:02

編集2019/05/16 02:14
can110

総合スコア38268

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

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

0

math.ceil(int(x * 1000) / 10) / 100 では如何でしょう?

x.py

python3

1import math 2 3def f(x): 4 return math.ceil(int(x * 1000) / 10) / 100 5 6TEST_CASES = ( 7 (0.0700, 0.07), 8 (0.07001, 0.07), 9 (0.0709, 0.07), 10 11 (0.071, 0.08), 12 (0.075, 0.08), 13 (0.080, 0.08), 14 (0.08001, 0.08), 15 (0.0809, 0.08), 16 17 (0.081, 0.09) 18) 19 20for x, y in TEST_CASES: 21 print(f(x) == y, "\t", x, "->", f(x))

実行例
イメージ説明

投稿2019/05/16 14:50

katoy

総合スコア22324

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

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

0

計算機の中の浮動小数点表現は2進数ですから0.07にぴったりとあう内部表現はありません。
3桁増やした固定小数点演算を行い、表示時に最下位を切り上げた後、3桁減らせばいいのでは?

投稿2019/05/16 12:31

sage

総合スコア1216

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

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

0

自己解決

ご回答いただいた方ありがとうございました。
どん方法もテストは通りませんでしたが
float(Decimal(str(value) ).quantize(Decimal('.00'), rounding=ROUND_UP))

これで上記のテストは通りました、テストを増やすしか確認する方法はないようでした

投稿2019/05/16 02:05

Kentaro0919

総合スコア258

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

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

can110

2019/05/16 02:10

それだと「ceil(0.07 * 100 ) / 100」したと同じ結果、たとえば「0.070000001」が「0.08」になっちゃうんですが、それでもよいのでしょうか?
Kentaro0919

2019/05/16 02:14

ceil(0.07 * 100 ) / 100 は 0.07 0.070 の場合失敗しましたが、上記に変えたらテストは通りました 不安は残ります
can110

2019/05/16 02:18

当方環境では value = 0.07000000001 ret = float(Decimal(str(value) ).quantize(Decimal('.00'), rounding=ROUND_UP)) print(ret) の結果は「0.08」になっちゃいますが、それでもよいのですか? また、何について不安があるのでしょうか?
cateye

2019/05/16 02:33 編集

>>> ceil(floor(0.07 * 100)) / 100 0.07 >>> b=ceil(floor(0.07 * 100)) / 100 >>> float(Decimal(str(b)).quantize(Decimal('.00'), rounding=ROUND_UP)) 0.07 >>> 合ってるかどうか分からんが・・・なんか。余計なことをやってるような^^;
Kentaro0919

2019/05/16 02:40

cateyeさんありがとうございます >>> ceil(floor(0.07 * 100)) / 100 0.070のパターンはうまくいきますが 切り上げがうまくいかないようです 出てくる元のデータは小数点第3位までのデータで2桁に繰り上げるのが正解でした。 0.070 -> 0.07 0.071 -> 0.08
cateye

2019/05/16 05:57 編集

>>> ceil(floor(0.071 * 1000)/10)/100 0.08 >>> ceil(floor(0.070 * 1000)/10)/100 0.07 >>> ceil(floor(0.079 * 1000)/10)/100 0.08 >>> ceil(floor(0.070 * 1000)/10)/100 0.07 >>> ceil(floor(0.06 * 1000)/10)/100 0.06 >>> ceil(floor(0.061 * 1000)/10)/100 0.07 >>> ceil(floor(0.0701 * 1000)/10)/100 0.07 >>> ceil(floor(0.0709 * 1000)/10)/100 0.07 >>> ceil(floor(0.071 * 1000)/10)/100 0.08 >>> ceil(floor(0.070 * 1000)/10)/100 0.07 >>>
guest

0

python

1>>> a= 0.07 2>>> print(a) 30.07 4>>> b= a * 100.0 5>>> print(b) 67.000000000000001 7>>> round(b) 87 9>>> b / 100 100.07 11>>>

投稿2019/05/16 00:58

cateye

総合スコア6851

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

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

cateye

2019/05/16 01:28 編集

ceil:小数点以下を切り上げ round:四捨五入 floor小数点以下を切り捨て 今回は、ceilを使っているので0.000000000000001が切り上げられる。 (少数を正確に浮動小数点数にすることは、普通出来ない) 環境はPython 3.7.3
guest

0

・0.07 * 100 の結果
・ceil(0.07 * 100 )の結果

がどうなるかをそれぞれ調べてみては

投稿2019/05/16 00:58

y_waiwai

総合スコア87784

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問