{ }codelper
roundingprinting decimalsP0232

Scaling a recipe to the head count

You rescale a cookbook's ingredient list to the number of servings you will make. The first line gives the cookbook's servings b and the servings to make t, separated by one space. The second line gives the number of ingredients n. Each of the next n lines gives an ingredient name, the cookbook amount a and a digit count d, separated by single spaces. The new amount x is the exact value of a × t ÷ b. If d is 1 or 2, round x to d decimal places and write exactly d digits after the decimal point (2.1 with d = 2 is 2.10). If d is 0, round x to an integer and write it without a decimal point. If d is -1, round x to the nearest multiple of 10, and if d is -2 to the nearest multiple of 100, and write it without a decimal point (237.8 with d = -1 is 240). If the rounded result is 0, write it to fit the digit count, such as 0, 0.0 or 0.00. To keep rounding unambiguous, no input makes the fractional part of x × 10^d lie between 0.4 and 0.6 inclusive. For each ingredient, in input order, print its name and new amount on one line, separated by one space.

Input
1 ≤ b ≤ 100, 1 ≤ t ≤ 100, 1 ≤ n ≤ 1,000, an ingredient name is 1–20 lowercase English letters (the same name may appear again), 0.01 ≤ a ≤ 10,000 written with 0–2 digits after the decimal point (e.g.
250, 1.5, 0.75), d is one of -2, -1, 0, 1, 2, no input has the fractional part of x × 10^d in 0.4–0.6
Output
n lines: ingredient name and new amount
Example 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
Example 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
Input (stdin)

When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).

$ Ready

Open this on a computer to write and run code. On mobile you can read the problem and the solutions.

In other languagesShow solutions by language · 8 languages

The tools that write exactly d decimals are 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) and Craykon Str.Fixed(x, d).
All of them pad 2.1 to 2.10 with the trailing zero.
Rounding-only functions such as Python round(x, 2), Craykon Mathf.Round(x, 2) and JS Math.round(x * 100) / 100 return a number, so printing it gives 2.1.
For a digit count of 0 or less the tools differ.
JS toFixed(-1) throws a RangeError.
In C, a negative precision in %.*f counts as no precision, so six decimals come out.
Craykon Mathf.Round accepts only 0–10 digits.
Python round(x, -1) works but returns a float, which prints as 240.0.
So divide by the unit 10^(-d), round to an integer and multiply back: Python round(x / 10) * 10 (round with one argument returns an int), JS/TS/Java Math.round, C llround, C++ std::llround, C# (long)Math.Round, Craykon Mathf.Round(x / 10) * 10.
The scale factor is a trap too.
In C, C++, Java and C#, writing a * (t / b) evaluates the integer t / b first, so 6 / 4 becomes 1.
Multiplying the double a first, as in a * t / b, makes it a floating-point division.
In Python 3, JS, TS and Craykon / is always floating-point division.
Rounding rules differ by language as well.
On an exact half, Python round and C# Math.Round go to the even neighbour, JS and Java Math.round go up, and C llround, C++ std::llround and Craykon Mathf.Round go away from zero.
Craykon and Java formatting round the visible decimal, while C, C++, Python, JS and C# formatting round the exact binary value (1.005 → 1.00).
This problem never gives values near such a boundary, so every method gives the same answer.
Java String.format and C# ToString/double.Parse follow the machine's locale, where the decimal point may be a comma, so pass Locale.ROOT or CultureInfo.InvariantCulture.

Pythonmain.py · 12 lines
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 lines
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 lines
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 lines
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 lines
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 lines
#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 lines
#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 lines
bt = Console.ReadNumbers();b = bt[0];t = bt[1];n = Console.ReadLine().ToNumber();for (i = 0; i < n; i++){    p = Console.ReadLine().Split();    a = p[1].ToNumber();    d = p[2].ToNumber();    x = a * t / b; // 크레이콘의 / 는 늘 소수까지 나눈다    값 = "";    if (d > 0)    {        값 = Str.Fixed(x, d);    }    else    {        // 수학.반올림의 자리는 0~10만 된다: 10, 100 단위는 나눠서 반올림하고 다시 곱한다        step = 1;        for (k = 0; k < 0 - d; k++)        {            step *= 10;        }        값 = Mathf.Round(x / step) * step;    }    Console.WriteLine(p[0] + " " + 값);}