{ }codelper
浮点精度四舍五入P0131

存款复利利息表

把钱存进银行,每月获得利息。
一行给出最初存入的金额 P(美元)、年利率 R(百分比)和月数 m,用空格分开。
P 和 R 都是小数点后恰好两位的数(例如 1000.00、3.25)。
每月月底,当月利息按 余额 × R ÷ 100 ÷ 12 计算。
利息四舍五入到美分(0.01 美元),美分以下恰好是 0.5 美分时进位。
把四舍五入后的利息加到余额上,下个月的利息用增加后的余额计算。
从第 1 个月到第 m 个月,每个月输出一行「月份编号(1 到 m)、当月利息、加上利息后的余额」,用一个空格分开。
最后一行输出 m 个月内获得的利息总和。
所有金额都写成小数点后恰好两位(例如 5.00、0.03)。

输入
0.01 ≤ P ≤ 1,000,000.00,0.00 ≤ R ≤ 20.00,1 ≤ m ≤ 120
输出
m 行:月份、利息、余额 / 最后一行:利息合计(金额保留两位小数)
样例 1 · stdin
1000.00 6.00 3
stdout
1 5.00 1005.00
2 5.03 1010.03
3 5.05 1015.08
15.08
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

算钱的正确做法是用整数美分,而不是浮点数(double)。
0.01、1005.03 这样的小数无法用二进制精确表示,用 float/double 累加并四舍五入 120 个月,可能会有某个月差 1 美分。
所以把输入字符串 "1000.05" 按小数点拆开,读成整数 100005 美分:Python s.split("."),JS/TS s.split("."),Java s.split("\\.")(是正则,所以要转义点),C# s.Split('.'),C scanf("%lld.%lld"),C++ s.find('.') 加 std::stoll,Craykon 行.替换(".", "").转数字()。
这样精确的利息是 余额 × 利率 ÷ 120000 美分,而 0.5 进位的四舍五入只用整数就是 (2 × 余额 × 利率 + 120000) ÷ 240000 的商。
取整函数的陷阱:Python round 和 C# Math.Round 默认是向偶数舍入(银行家舍入),所以 252.5 会变成 252。
C# Math.Round(x, MidpointRounding.AwayFromZero)、Java Math.round、JS/TS Math.round、C/C++ round、Craykon 数学.四舍五入 会把 0.5 进位(负数的规则各语言不同)。
不过这些函数接收的是浮点数,要判断是否恰好是 0.5,用整数计算更稳妥。
只做整数除法 余额 * 利率 / 120000 得到的是截断而不是四舍五入。
还要注意大小。
2 × 余额 × 利率可达 3×10^12,超过 32 位 int,所以 Java、C# 要用 long,C、C++ 要用 long long。
Python 整数没有大小限制,JS、TS、Craykon 的数在 2^53 以内都是精确整数,没有问题。
输出用商和余数拼出 "5.03",余数前面补 0 成两位:Python f"{c % 100:02d}",JS/TS padStart(2, "0"),Java String.format("%02d"),C# :D2,C %02lld,Craykon 左填充(2, "0")。

Pythonmain.py · 21 行
def hundredths(s):    # "1000.05" → 100005 (소수점 아래는 언제나 두 자리)    whole, frac = s.split(".")    return int(whole) * 100 + int(frac)  def money(c):    return f"{c // 100}.{c % 100:02d}"  p, r, m = input().split()bal = hundredths(p)  # 잔액(센트)rate = hundredths(r)  # 연 이율(0.01% 단위): 3.25% → 325total = 0for month in range(1, int(m) + 1):    # 정확한 이자 = bal × rate / 120000 센트. 반올림(0.5는 올림) = (2 × 분자 + 분모) // (2 × 분모)    interest = (2 * bal * rate + 120000) // 240000    bal += interest    total += interest    print(month, money(interest), money(bal))print(money(total))
JavaScriptmain.js · 20 行
const [p, r, m] = require("fs").readFileSync(0, "utf8").trim().split(/\s+/);// "1000.05" → 100005 (소수점 아래는 언제나 두 자리). 정수로만 계산하면 실수 오차가 없다const hundredths = (s) => {  const [whole, frac] = s.split(".");  return Number(whole) * 100 + Number(frac);};const money = (c) => Math.floor(c / 100) + "." + String(c % 100).padStart(2, "0");let bal = hundredths(p); // 잔액(센트)const rate = hundredths(r); // 연 이율(0.01% 단위)let total = 0;const out = [];for (let month = 1; month <= Number(m); month++) {  // 정확한 이자 = bal × rate / 120000 센트, 0.5는 올림. 최대 3×10^12라 number로 정확하다  const interest = Math.floor((2 * bal * rate + 120000) / 240000);  bal += interest;  total += interest;  out.push(month + " " + money(interest) + " " + money(bal));}out.push(money(total));console.log(out.join("\n"));
TypeScriptmain.ts · 21 行
import { readFileSync } from "node:fs";const [p, r, m]: string[] = readFileSync(0, "utf8").trim().split(/\s+/);// "1000.05" → 100005 (소수점 아래는 언제나 두 자리). 정수로만 계산하면 실수 오차가 없다const hundredths = (s: string): number => {  const [whole, frac] = s.split(".");  return Number(whole) * 100 + Number(frac);};const money = (c: number): string => Math.floor(c / 100) + "." + String(c % 100).padStart(2, "0");let bal: number = hundredths(p); // 잔액(센트)const rate: number = hundredths(r); // 연 이율(0.01% 단위)let total = 0;const out: string[] = [];for (let month = 1; month <= Number(m); month++) {  // 정확한 이자 = bal × rate / 120000 센트, 0.5는 올림. 최대 3×10^12라 number로 정확하다  const interest: number = Math.floor((2 * bal * rate + 120000) / 240000);  bal += interest;  total += interest;  out.push(month + " " + money(interest) + " " + money(bal));}out.push(money(total));console.log(out.join("\n"));
JavaMain.java · 31 行
import java.util.Scanner; public class Main {    // "1000.05" → 100005 (소수점 아래는 언제나 두 자리)    static long hundredths(String s) {        String[] parts = s.split("\\.");        return Long.parseLong(parts[0]) * 100 + Long.parseLong(parts[1]);    }     static String money(long c) {        return c / 100 + "." + String.format("%02d", c % 100);    }     public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        long bal = hundredths(sc.next()); // 잔액(센트)        long rate = hundredths(sc.next()); // 연 이율(0.01% 단위)        int m = sc.nextInt();        long total = 0;        StringBuilder out = new StringBuilder();        for (int month = 1; month <= m; month++) {            // 정확한 이자 = bal × rate / 120000 센트, 0.5는 올림. 곱이 int를 넘으니 long            long interest = (2 * bal * rate + 120000) / 240000;            bal += interest;            total += interest;            out.append(month).append(' ').append(money(interest)).append(' ').append(money(bal)).append('\n');        }        out.append(money(total)).append('\n');        System.out.print(out);    }}
C#Main.cs · 34 行
using System;using System.Text; class Program{    // "1000.05" → 100005 (소수점 아래는 언제나 두 자리)    static long Hundredths(string s)    {        string[] parts = s.Split('.');        return long.Parse(parts[0]) * 100 + long.Parse(parts[1]);    }     static string Money(long c) => $"{c / 100}.{c % 100:D2}";     static void Main()    {        string[] t = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);        long bal = Hundredths(t[0]); // 잔액(센트)        long rate = Hundredths(t[1]); // 연 이율(0.01% 단위)        int m = int.Parse(t[2]);        long total = 0;        var sb = new StringBuilder();        for (int month = 1; month <= m; month++)        {            // 정확한 이자 = bal × rate / 120000 센트, 0.5는 올림. Math.Round는 기본이 짝수 쪽이라 쓰지 않는다            long interest = (2 * bal * rate + 120000) / 240000;            bal += interest;            total += interest;            sb.Append(month).Append(' ').Append(Money(interest)).Append(' ').Append(Money(bal)).Append('\n');        }        sb.Append(Money(total)).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 31 行
#include <iomanip>#include <iostream>#include <string> // "1000.05" → 100005 (소수점 아래는 언제나 두 자리)long long hundredths(const std::string& s) {    auto dot = s.find('.');    return std::stoll(s.substr(0, dot)) * 100 + std::stoll(s.substr(dot + 1));} std::string money(long long c) {    std::string cents = std::to_string(c % 100);    return std::to_string(c / 100) + "." + (cents.size() < 2 ? "0" : "") + cents;} int main() {    std::string p, r;    int m;    std::cin >> p >> r >> m;    long long bal = hundredths(p);  // 잔액(센트)    long long rate = hundredths(r); // 연 이율(0.01% 단위)    long long total = 0;    for (int month = 1; month <= m; month++) {        // 정확한 이자 = bal × rate / 120000 센트, 0.5는 올림. 곱이 int를 넘으니 long long        long long interest = (2 * bal * rate + 120000) / 240000;        bal += interest;        total += interest;        std::cout << month << ' ' << money(interest) << ' ' << money(bal) << '\n';    }    std::cout << money(total) << '\n';}
Cmain.c · 34 行
#include <stdio.h> /* "1000.05"를 정수 1000과 05로 따로 읽는다 — 소수는 언제나 두 자리다 */long long read_hundredths(void) {    long long whole, frac;    scanf("%lld.%lld", &whole, &frac);    return whole * 100 + frac;} void print_money(long long c) {    printf("%lld.%02lld", c / 100, c % 100);} int main(void) {    long long bal = read_hundredths();  /* 잔액(센트) */    long long rate = read_hundredths(); /* 연 이율(0.01% 단위) */    int m;    scanf("%d", &m);    long long total = 0;    for (int month = 1; month <= m; month++) {        /* 정확한 이자 = bal × rate / 120000 센트, 0.5는 올림. 곱이 int를 넘으니 long long */        long long interest = (2 * bal * rate + 120000) / 240000;        bal += interest;        total += interest;        printf("%d ", month);        print_money(interest);        putchar(' ');        print_money(bal);        putchar('\n');    }    print_money(total);    putchar('\n');    return 0;}
Craykonmain.cray · 25 行
백분(줄){    // "1000.05" → "100005" → 100005 (소수점 아래는 언제나 두 자리)    返回 줄.替换(".", "").转数字();} 돈(c){    返回 数学.商(c, 100) + "." + ("" + c % 100).左填充(2, "0");} t = 控制台.读行().分割(" ");bal = 백분(t[0]); // 잔액(센트)rate = 백분(t[1]); // 연 이율(0.01% 단위)m = t[2].转数字();total = 0;循环 (month = 1; month <= m; month++){    // 정확한 이자 = bal × rate / 120000 센트, 0.5는 올림. 최대 3×10^12라 수가 정확하다    interest = 数学.商(2 * bal * rate + 120000, 240000);    bal += interest;    total += interest;    控制台.输出(month + " " + 돈(interest) + " " + 돈(bal));}控制台.输出(돈(total));