ABC169 C - Multiplication 3
備忘録
問題
回答
import sys sys.setrecursionlimit(10000000) import os import math import bisect import collections import itertools import heapq import re import queue from decimal import Decimal # import fractions ii = lambda: int(sys.stdin.buffer.readline().rstrip()) il = lambda: list(map(int, sys.stdin.buffer.readline().split())) fl = lambda: list(map(float, sys.stdin.buffer.readline().split())) iln = lambda n: [int(sys.stdin.buffer.readline().rstrip()) for _ in range(n)] iss = lambda: sys.stdin.buffer.readline().decode().rstrip() sl = lambda: list(map(str, sys.stdin.buffer.readline().decode().split())) isn = lambda n: [sys.stdin.buffer.readline().decode().rstrip() for _ in range(n)] lcm = lambda x, y: (x * y) // math.gcd(x, y) # lcm = lambda x, y: (x * y) // fractions.gcd(x, y) MOD = 10 ** 9 + 7 MAX = float('inf') def main(): if os.getenv("LOCAL"): sys.stdin = open("input.txt", "r") A, B = fl() A = int(A) B = int(B * 1000) print((A * B) // 1000) if __name__ == '__main__': main()
考え方
B
は小数第2位まで与えられるため、浮動小数点数による誤差が発生する可能性がある。
そのため、素直にmath.floor(A*B)
と回答すると、正解にはならない。
誤差の問題を解決するために、あらかじめB * 1000
でB
が小数点を持たない整数にしておき、
A*B
の後に1000
で割ることで回答を得られる。
小数点の誤差は2進数で表現できないために発生する。
解説は下記のリンクが参考になった。
小数計算の誤差 0.1 + 0.2 が 0.30000000000000004 になる理由 | あぱーブログ
似た傾向の問題として、√を扱う問題も存在する。
C - Sqrt Inequality
どちらの問題も与えられた数値を整数として扱うことが求められる。
追加ケースにより追記(2020/06/01 23:00)
コンテスト後、ジャッジにケースが追加されたため、
上記のB * 1000
方式では不正解となった。
そもそも浮動小数点数型(float
)は値を受け取った時点で誤差が発生しているため、
文字列として扱うことで正確に使用することが出来る。
例1:整数部と小数部を文字列として受け取り、数値に変換する例
Submission #13930455 - AtCoder Beginner Contest 169
例2:文字列からDecimal
に変換する例
Submission #13927854 - AtCoder Beginner Contest 169