{ }codelper
반올림소수 자리 출력P0232

사람 수에 맞춰 바꾸는 요리 분량

요리책의 분량표를 만들 사람 수에 맞춰 바꾼다. 첫 줄에 요리책이 정한 인분 b와 만들 인분 t가 빈칸 하나로 띄워 주어진다. 둘째 줄에 재료 수 n이 주어진다. 다음 n줄에는 한 줄에 재료 이름, 요리책의 양 a, 자리 수 d가 빈칸 하나씩으로 띄워 주어진다. 바꾼 양 x는 a × t ÷ b를 정확하게 계산한 값이다. d가 1이나 2이면 x를 소수 d째 자리까지 반올림하고, 소수점 아래를 정확히 d자리로 쓴다(2.1은 d가 2이면 2.10). d가 0이면 x를 정수로 반올림해 소수점 없이 쓴다. d가 -1이면 x를 가장 가까운 10의 배수로, d가 -2이면 가장 가까운 100의 배수로 반올림해 소수점 없이 쓴다(237.8은 d가 -1이면 240). 반올림한 결과가 0이면 그 자리 수에 맞춰 0, 0.0, 0.00처럼 쓴다. 반올림이 헷갈리지 않도록, x에 10^d를 곱한 값의 소수 부분이 0.4 이상 0.6 이하가 되는 입력은 주어지지 않는다. 재료마다 입력 차례대로 한 줄에 재료 이름과 바꾼 양을 빈칸 하나로 띄워 출력하라.

입력
1 ≤ b ≤ 100, 1 ≤ t ≤ 100, 1 ≤ n ≤ 1,000, 재료 이름은 영어 소문자 1~20글자(같은 이름이 또 나올 수 있다), 0.01 ≤ a ≤ 10,000이고 a는 소수점 아래를 0~2자리로 쓴다(예: 250, 1.5, 0.75), d는 -2, -1, 0, 1, 2 중 하나, x × 10^d의 소수 부분이 0.4~0.6인 입력은 없다
출력
n줄: 재료 이름과 바꾼 양
예시 1 · stdin
4 6
6
flour 420 -1
milk 330 0
sugar 12.38 1
salt 1.4 2
yeast 0.08 2
butter 55 -2
stdout
flour 630
milk 495
sugar 18.6
salt 2.10
yeast 0.12
butter 100
예시 2 · stdin
3 1
4
water 1000 0
pepper 0.5 2
rice 20 -1
tiny 1 -2
stdout
water 333
pepper 0.17
rice 10
tiny 0
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이

소수 d자리로 맞춰 쓰는 도구는 Python f"{x:.{d}f}", JS·TS x.toFixed(d), Java String.format("%." + d + "f", x), C# x.ToString("F" + d), C printf("%.*f", d, x), C++ std::fixed << std::setprecision(d), 크레이콘 글자.소수자리맞추기(x, d)예요.
모두 2.1을 2.10처럼 뒤의 0까지 채워 줘요.
반올림만 하는 Python round(x, 2), 크레이콘 수학.반올림(x, 2), JS Math.round(x * 100) / 100은 수를 돌려줘서 그대로 찍으면 2.1이 나와요.
자리가 0 이하이면 도구마다 달라요.
JS toFixed(-1)은 RangeError를 내요.
C %.*f에 음수 자리를 주면 자리를 안 준 것으로 쳐서 소수 여섯 자리가 나와요.
크레이콘 수학.반올림은 자리로 0~10만 받아요.
Python round(x, -1)은 되지만 실수를 돌려줘서 240.0으로 찍혀요.
그래서 10^(-d) 단위로 나눠 정수로 반올림하고 다시 곱해요: Python round(x / 10) * 10(인수가 하나인 round는 정수를 돌려줘요), JS·TS·Java Math.round, C llround, C++ std::llround, C# (long)Math.Round, 크레이콘 수학.반올림(x / 10) * 10.
배율도 함정이에요.
C·C++·Java·C#에서 a * (t / b)라고 쓰면 정수끼리인 t / b가 먼저 계산되어 6 / 4가 1이 돼요.
a * t / b처럼 실수 a부터 곱하면 실수 나눗셈이 돼요.
Python 3·JS·TS·크레이콘의 /는 언제나 실수 나눗셈이에요.
반올림 규칙도 언어마다 달라요.
정확히 반인 값을 Python round와 C# Math.Round는 짝수 쪽으로, JS·Java Math.round는 큰 쪽으로, C llround·C++ std::llround·크레이콘 수학.반올림은 0에서 먼 쪽으로 보내요.
크레이콘과 Java 서식은 보이는 십진수를 반올림하지만, C·C++·Python·JS·C# 서식은 이진수로 저장된 값을 반올림해요(1.005 → 1.00).
이 문제는 그런 경계에 가까운 값을 주지 않아서 어느 방법이든 답이 같아요.
Java String.format과 C# ToString·double.Parse는 실행 환경의 지역 설정을 따라 소수점이 쉼표가 될 수 있으니 Locale.ROOT·CultureInfo.InvariantCulture를 줘요.

Pythonmain.py · 12 줄
b, t = map(int, input().split())n = int(input())for _ in range(n):    name, a, d = input().split()    d = int(d)    x = float(a) * t / b  # /는 늘 실수 나눗셈이다    if d > 0:        print(name, f"{x:.{d}f}")    else:        # 자리가 0 이하이면 10^(-d) 단위로: round(x / 단위)는 정수를 돌려준다        step = 10 ** -d        print(name, round(x / step) * step)
JavaScriptmain.js · 16 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const [b, t] = lines[0].trim().split(/\s+/).map(Number);const n = Number(lines[1]);const out = [];for (let i = 0; i < n; i++) {  const [name, a, ds] = lines[2 + i].trim().split(/\s+/);  const d = Number(ds);  const x = (Number(a) * t) / b;  if (d > 0) {    out.push(`${name} ${x.toFixed(d)}`); // toFixed는 0~100자리만 받는다  } else {    const step = 10 ** -d;    out.push(`${name} ${Math.round(x / step) * step}`);  }}console.log(out.join("\n"));
TypeScriptmain.ts · 17 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const [b, t] = lines[0].trim().split(/\s+/).map(Number);const n = Number(lines[1]);const out: string[] = [];for (let i = 0; i < n; i++) {  const [name, a, ds] = lines[2 + i].trim().split(/\s+/);  const d = Number(ds);  const x: number = (Number(a) * t) / b;  if (d > 0) {    out.push(`${name} ${x.toFixed(d)}`); // toFixed는 0~100자리만 받는다  } else {    const step = 10 ** -d;    out.push(`${name} ${Math.round(x / step) * step}`);  }}console.log(out.join("\n"));
JavaMain.java · 27 줄
import java.util.Locale;import java.util.Scanner; public class Main {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        int b = sc.nextInt(), t = sc.nextInt();        int n = sc.nextInt();        StringBuilder out = new StringBuilder();        for (int i = 0; i < n; i++) {            String name = sc.next();            double a = Double.parseDouble(sc.next());            int d = sc.nextInt();            double x = a * t / b; // a가 double이라 실수 나눗셈이 된다            out.append(name).append(' ');            if (d > 0) {                // Locale.ROOT: 지역 설정과 상관없이 소수점을 점으로 쓴다                out.append(String.format(Locale.ROOT, "%." + d + "f", x));            } else {                long step = d == 0 ? 1 : d == -1 ? 10 : 100;                out.append(Math.round(x / step) * step);            }            out.append('\n');        }        System.out.print(out);    }}
C#Main.cs · 34 줄
using System;using System.Globalization;using System.Text; class Program{    static void Main()    {        var inv = CultureInfo.InvariantCulture;        string[] bt = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);        int b = int.Parse(bt[0]), t = int.Parse(bt[1]);        int n = int.Parse(Console.ReadLine());        var out_ = new StringBuilder();        for (int i = 0; i < n; i++)        {            string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);            double a = double.Parse(p[1], inv);            int d = int.Parse(p[2]);            double x = a * t / b;            out_.Append(p[0]).Append(' ');            if (d > 0)            {                out_.Append(x.ToString("F" + d, inv)); // "F2": 소수 두 자리            }            else            {                long step = d == 0 ? 1 : d == -1 ? 10 : 100;                out_.Append((long)Math.Round(x / step) * step);            }            out_.Append('\n');        }        Console.Write(out_);    }}
C++main.cpp · 23 줄
#include <cmath>#include <iomanip>#include <iostream>#include <string> int main() {    int b, t, n;    std::cin >> b >> t >> n;    for (int i = 0; i < n; i++) {        std::string name;        double a;        int d;        std::cin >> name >> a >> d;        double x = a * t / b;        std::cout << name << ' ';        if (d > 0) {            std::cout << std::fixed << std::setprecision(d) << x << '\n';        } else {            long long step = d == 0 ? 1 : d == -1 ? 10 : 100;            std::cout << std::llround(x / step) * step << '\n';        }    }}
Cmain.c · 21 줄
#include <math.h>#include <stdio.h> int main(void) {    int b, t, n;    scanf("%d %d %d", &b, &t, &n);    for (int i = 0; i < n; i++) {        char name[32];        double a;        int d;        scanf("%31s %lf %d", name, &a, &d);        double x = a * t / b; /* a가 double이라 실수 나눗셈이 된다 */        if (d > 0) {            printf("%s %.*f\n", name, d, x); /* 자리 수를 인수로 넘긴다 */        } else {            long long step = d == 0 ? 1 : d == -1 ? 10 : 100;            printf("%s %lld\n", name, llround(x / step) * step);        }    }    return 0;}
Craykonmain.cray · 27 줄
bt = 콘솔.수들읽기();b = bt[0];t = bt[1];n = 콘솔.줄읽기().수로변환();반복 (i = 0; i < n; i++){    p = 콘솔.줄읽기().나누기();    a = p[1].수로변환();    d = p[2].수로변환();    x = a * t / b; // 크레이콘의 / 는 늘 소수까지 나눈다    값 = "";    만약 (d > 0)    {        값 = 글자.소수자리맞추기(x, d);    }    아니면    {        // 수학.반올림의 자리는 0~10만 된다: 10, 100 단위는 나눠서 반올림하고 다시 곱한다        step = 1;        반복 (k = 0; k < 0 - d; k++)        {            step *= 10;        }        값 = 수학.반올림(x / step) * step;    }    콘솔.쓰기(p[0] + " " + 값);}