{ }codelper
n行の読み込み浮動小数点の誤差型変換P0043

持っているお金とぴったり?

一行目に品物の数 n が与えられ、続く n 行に値段が一行に一つずつ与えられる。
最後の行には持っているお金 m が与えられる。
値段と m はすべて小数点以下ちょうど二桁で書かれた数である(例:0.10、12.30、7.05)。
値段の合計が m とちょうど等しければ "はい"、そうでなければ "いいえ" を出力せよ。

入力
1 ≤ n ≤ 1,000、0.01 ≤ 値段 ≤ 10,000.00、0.00 ≤ m ≤ 10,000,000.00
出力
"はい" または "いいえ"
例 1 · stdin
2
0.10
0.20
0.30
stdout
はい
例 2 · stdin
3
1.50
2.25
0.29
4.05
stdout
いいえ
main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

値段を実数(double)で足して == で比べると間違えます。
0.1 と 0.2 は二進数で正確に書けないので、0.1 + 0.2 は 0.30000000000000004 です。
Python float、JS・TS number、Java・C・C++ double はどれも同じ IEEE 754 倍精度なので、どれでも 0.1 + 0.2 == 0.3 は偽です。
Craykon の数も JS の double なので比較は偽ですが、コンソール.書く が小数第 9 位で丸めて 0.3 と表示するので、目では誤差が見えません。
100 を掛けて整数にするときにも落とし穴があります:C・C++・Java・C# の (int)(x * 100)、Python int()、JS Math.trunc は 0 の方へ切り捨てますが、0.29 * 100 は 28.999999999999996 なので 28 になります — 変換するなら丸め(round、Math.round)を使います。
abs(a - b) < 1e-9 のような許容誤差も危険です:一千万あたりでは隣り合う double の間隔そのものが約 1.9e-9 なので、同じ金額でも違うと出ます。
いちばん確実なのは最初から整数のセントで読むことです。
文字から点を取れば("12.34" → 1234)終わり:Python int(s.replace(".", ""))、Java Long.parseLong、JS・TS Number、C scanf("%lld.%lld", &w, &f)、Craykon 行.置き換え(".", "").数に()。
最大の合計 10 億セントは 32 ビット int(約 21 億)に収まりますが、余裕を持つなら C・C++ long long、Java・C# long を使います。
C# には十進の実数 decimal があり、decimal.Parse で足すと 0.1 + 0.2 == 0.3 が真になります(Java は BigDecimal、Python は decimal.Decimal で同じことができます)。

Pythonmain.py · 10 行
# 값은 소수 두 자리로 정확히 주어지므로 점을 빼면 바로 '센트(1/100)' 단위 정수다def cents(s):    return int(s.strip().replace(".", "")) n = int(input())total = 0for _ in range(n):    total += cents(input())m = cents(input())print("はい" if total == m else "いいえ")
JavaScriptmain.js · 8 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");// "12.34" → 1234: 점을 빼면 센트 단위 정수가 된다const cents = (s) => Number(s.trim().replace(".", ""));const n = Number(lines[0]);let total = 0;for (let i = 1; i <= n; i++) total += cents(lines[i]);const m = cents(lines[n + 1]);console.log(total === m ? "はい" : "いいえ");
TypeScriptmain.ts · 9 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");// "12.34" → 1234: 점을 빼면 센트 단위 정수가 된다const cents = (s: string): number => Number(s.trim().replace(".", ""));const n: number = Number(lines[0]);let total = 0;for (let i = 1; i <= n; i++) total += cents(lines[i]);const m: number = cents(lines[n + 1]);console.log(total === m ? "はい" : "いいえ");
JavaMain.java · 19 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader; public class Main {    // "12.34" → 1234: 점을 빼면 센트 단위 정수가 된다    static long cents(String s) {        return Long.parseLong(s.trim().replace(".", ""));    }     public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(in.readLine().trim());        long total = 0;        for (int i = 0; i < n; i++) total += cents(in.readLine());        long m = cents(in.readLine());        System.out.println(total == m ? "はい" : "いいえ");    }}
C#Main.cs · 14 行
using System; class Program{    static void Main()    {        // C#의 decimal은 십진수라 0.1 + 0.2 == 0.3 이 참이다        int n = int.Parse(Console.ReadLine());        decimal total = 0m;        for (int i = 0; i < n; i++) total += decimal.Parse(Console.ReadLine());        decimal m = decimal.Parse(Console.ReadLine());        Console.WriteLine(total == m ? "はい" : "いいえ");    }}
C++main.cpp · 21 行
#include <iostream>#include <string> // "12.34" → 1234: 점을 빼면 센트 단위 정수가 된다long long cents(std::string s) {    s.erase(s.find('.'), 1);    return std::stoll(s);} int main() {    int n;    std::cin >> n;    long long total = 0;    std::string s;    for (int i = 0; i < n; i++) {        std::cin >> s;        total += cents(s);    }    std::cin >> s;    std::cout << (total == cents(s) ? "はい" : "いいえ") << "\n";}
Cmain.c · 18 行
#include <stdio.h> /* "12.34"를 정수 12와 34로 따로 읽는다 — 소수는 정확히 두 자리라 34는 센트다 */long long read_cents(void) {    long long whole, frac;    scanf("%lld.%lld", &whole, &frac);    return whole * 100 + frac;} int main(void) {    int n;    scanf("%d", &n);    long long total = 0;    for (int i = 0; i < n; i++) total += read_cents();    long long m = read_cents();    puts(total == m ? "はい" : "いいえ");    return 0;}
Craykonmain.cray · 14 行
센트(줄){    // "12.34" → "1234" → 1234    返す 줄.空白除去().置き換え(".", "").数に();} n = コンソール.行読み().数に();합 = 0;繰り返す (i = 0; i < n; i++){    합 += 센트(コンソール.行読み());}m = 센트(コンソール.行読み());コンソール.書く(합 == m ? "はい" : "いいえ");