LoginSignup
KKkbt
@KKkbt (Kenta Kubota)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

AtCoder Regular Contest 118のA問題について

AtCoder Regular Contest 118のA問題が解けなかった、、、

AtCoder Regular Contest 118 A問題を解こうとしたのですが、下のコードで2つだけWAが出て上手く行きませんでした、、
どなたか何が間違っているか教えていただけますでしょうか?

よろしくお願いします!

import math


def main():
    t, n = map(int, input().split())
    ans = (n // t) * (100 + t)

    loop_len = 101 * t
    expected_repetition = n % t

    pre_price = 0
    repetition = 0
    p = 1
    while True:
        price = math.floor(p * (1 + t * 10 ** -2))
        price_difference = price - pre_price
        if repetition == expected_repetition:
            ans += pre_price - 1
            break
        elif price_difference >= 2:
            repetition += 1
        pre_price = price
        p += 1

    print(ans)


if __name__ == "__main__":
    main()
0

2Answer

小数計算で足し算は避けた方がいいんですかね,,?

そうですね、小数の計算はできるかぎり避けたほうがいいと思います。
たまに、誤差を許容してくれる問題もありますが…。
(ABC-117 A - Entrance Examination)

小数で誤差を生まないために私が思いつくのは、以下の3つの方法です。

①小数にならないように計算する

今回の例のように、小数になる掛け算などを後回しにして小数の計算誤差を生じさせなくすることができます。

print(0.3 - 0.2)
#0.09999999999999998

print((3-2)*0.1)
#0.1

②Decimalを使う

小数になるところをあらかじめdecimal型に変換しておいて、誤差を生じさせなくすることができます。
Decimalに小数を直接渡すときは文字列で渡すというところに注意が必要です。

from decimal import Decimal

print(0.3 - 0.2)
#0.09999999999999998

print(Decimal(0.3) - Decimal(0.2))
#0.09999999999999997779553950750

print(Decimal('0.3') - Decimal('0.2'))
#0.1

③マイナスを使った切り捨てを行う

こちらに詳しく解説された記事があります。
ARC-062 C-AtCoDeerくんと選挙速報: ceil関数の割り算に気をつけよう

import math

a = 111111111111111111
b = 9
print(math.ceil(a/b))
#12345679012345680 → 誤差が生じている

print(-(-a//b))
#12345679012345679


#DecimalでもOK
from decimal import Decimal
print(math.ceil(Decimal(a)/b))
#12345679012345679
1

Comments

  1. @KKkbt

    Questioner
    返信遅くなりました,すみません!

    ありがとうございます!参考にします!

math.floor(p * (1 + t * 10 ** -2))
ここで小数計算による誤差が生じています。

math.floor(p * (100 + t) * 10 ** -2)
とすればACでした。

import math
p=100
t = 101
print(p * (1 + t * 10 ** -2))
print(p * (100 + t) * 10 ** -2)

#200.99999999999997
#201.0

0

Comments

  1. @KKkbt

    Questioner
    @YottyPG 様,

    ありがとうございます!納得です,,
    小数計算で足し算は避けた方がいいんですかね,,?

Your answer might help someone💌