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

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

ただいまの
回答率

90.50%

  • Python 3.x

    9865questions

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

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

解決済

回答 6

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 190

Kentaro0919

score 223

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

今のコード

from math import ceil

ceil(0.07 * 100 ) / 100
0.08

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

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

float(Decimal(0.079).quantize(Decimal('.00')))


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

期待値は

def test_95_per_5_Mbps_007():
    assert get_kakin(0.07) == 0.07

def test_95_per_5_Mbps_0070():
    assert get_kakin(0.070) == 0.07

def test_95_per_5_Mbps_0071():
    assert get_kakin(0.071) == 0.08

def test_95_per_5_Mbps_0072():
    assert get_kakin(0.072) == 0.08

def test_95_per_5_Mbps_0075():
    assert get_kakin(0.075) == 0.08

def test_95_per_5_Mbps_0076():
    assert get_kakin(0.076) == 0.08

def test_95_per_5_Mbps_0079():
    assert get_kakin(0.079) == 0.08
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • quiqui

    2019/05/16 10:29

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

    キャンセル

  • can110

    2019/05/16 10:30

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

    キャンセル

  • cateye

    2019/05/16 11:00 編集

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

    キャンセル

回答 6

+1

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

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

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

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

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

def func(val):
    ret = Decimal(str(val))
    ret = ret.quantize(Decimal('.000'), ROUND_HALF_UP) # 小数第4位を四捨五入
    ret = ret.quantize(Decimal('.00'), ROUND_UP)       # 小数第3位を切り上げ
    return ret

for val in [0.07, 0.07001, 0.0701, 0.0704, 0.0705, 0.071]:
    ret = func(val)
    print('{} -> {}'.format(val, func(val)))

"""
0.07 -> 0.07
0.07001 -> 0.07
0.0701 -> 0.07
0.0704 -> 0.07
0.0705 -> 0.08
0.071 -> 0.08
"""

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

check解決した方法

0

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/16 11:10

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

    キャンセル

  • 2019/05/16 11:14

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

    キャンセル

  • 2019/05/16 11:18

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

    キャンセル

  • 2019/05/16 11:25 編集

    >>> 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
    >>>
    合ってるかどうか分からんが・・・なんか。余計なことをやってるような^^;

    キャンセル

  • 2019/05/16 11:40

    cateyeさんありがとうございます

    >>> ceil(floor(0.07 * 100)) / 100
    0.070のパターンはうまくいきますが 切り上げがうまくいかないようです



    出てくる元のデータは小数点第3位までのデータで2桁に繰り上げるのが正解でした。
    0.070 -> 0.07
    0.071 -> 0.08

    キャンセル

  • 2019/05/16 14:55 編集

    >>> 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
    >>>

    キャンセル

0

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

>>> a= 0.07
>>> print(a)
0.07
>>> b= a * 100.0
>>> print(b)
7.000000000000001
>>> round(b)
7
>>> b / 100
0.07
>>> 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/16 10:05 編集

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

    キャンセル

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

x.py

import math

def f(x):
        return math.ceil(int(x * 1000) / 10) / 100

TEST_CASES = (
    (0.0700,  0.07),
    (0.07001, 0.07),
    (0.0709,  0.07),

    (0.071,   0.08),
    (0.075,   0.08),
    (0.080,   0.08),
    (0.08001, 0.08),
    (0.0809,  0.08),

    (0.081,   0.09)
)

for x, y in TEST_CASES:
    print(f(x) == y, "\t", x, "->", f(x))

実行例
イメージ説明

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • Python 3.x

    9865questions

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