💰《Python 金额系统从 0 到 1》

44 阅读2分钟

① 一句话架构:金额系统 4 层模型 🏗️

层级技术精度示例
存储层int 分厘0 误差price = 12345 # 123.45 元
计算层Decimal用户指定Decimal('123.45')
展示层str 格式化2 位小数¥123.45
导出层CSV/Excel2 位小数123.45

口诀:“分厘存,Decimal 算,字符串秀,Excel 出” 🎵


② 存储层:分厘存储(0 误差)💰

class Amount:
    def __init__(self, fen: int):
        self.fen = fen

    def to_yuan(self) -> str:
        return f"{self.fen / 100:.2f}"

    def __add__(self, other):
        return Amount(self.fen + other.fen)

    def __str__(self):
        return f"¥{self.to_yuan()}"

# 使用
a = Amount(12345)  # 123.45 元
b = Amount(67890)  # 678.90 元
print(a + b)       # ¥802.35

结论:分厘存储 = 0 误差,整数运算快!


③ 计算层:Decimal 汇率(无误差)🌍

from decimal import Decimal, ROUND_HALF_UP

def exchange(amount_fen: int, rate: Decimal) -> int:
    """分 → 分,按汇率,四舍五入到分"""
    result = (Decimal(amount_fen) * rate).quantize(Decimal('1'), ROUND_HALF_UP)
    return int(result)

# 使用
rate = Decimal('7.1234')  # 1 USD = 7.1234 CNY
usd_fen = 10000           # 100 USD
cny_fen = exchange(usd_fen, rate)
print(f"{usd_fen//100} USD → {cny_fen//100} CNY")  # 100 USD → 712 CNY

结论:quantize 控制小数位,避免银行家舍入误差!


④ 展示层:彩虹格式化(炫彩)🌈

import math, random

def rainbow_money(yuan: float) -> str:
    """彩虹渐变金额"""
    r = int(255 * (1 + math.cos(yuan * 2 * math.pi)) / 2)
    g = int(255 * (1 + math.cos(yuan * 2 * math.pi + 2)) / 2)
    b = int(255 * (1 + math.cos(yuan * 2 * math.pi + 4)) / 2)
    return f"\033[38;2;{r};{g};{b}{yuan:.2f}\033[0m"

# 使用
print(rainbow_money(123.45))  # 彩虹 ¥123.45

⑤ 批量对账:CSV + pandas 📊

import pandas as pd

# 生成示例数据
data = [
    {"item": "咖啡", "fen": 3500},
    {"item": "三明治", "fen": 7800},
    {"item": "蛋糕", "fen": 4500},
]
df = pd.DataFrame(data)
df["yuan"] = df["fen"] / 100
df["formatted"] = df["yuan"].apply(lambda x: f"¥{x:.2f}")
df.to_csv("amounts.csv", index=False)
print(df)

结果:可直接发给财务/客户,零误差对账


⑥ 万能解毒剂:检查清单 ✅

场景解毒法
金额存储int 分厘 或 Decimal
汇率换算quantize(Decimal('1'), ROUND_HALF_UP)
显示格式化f"¥{yuan:.2f}"
批量导出pandas.to_csv(float_format='%.2f')

⑦ 彩蛋:终端彩虹金额器(15 行)🌈

import decimal, random, math, os
from decimal import Decimal

def rainbow_money(yuan):
    r = int(255 * (1 + math.cos(float(yuan) * 2 * math.pi)) / 2)
    g = int(255 * (1 + math.cos(float(yuan) * 2 * math.pi + 2)) / 2)
    b = int(255 * (1 + math.cos(float(yuan) * 2 * math.pi + 4)) / 2)
    return f"\033[38;2;{r};{g};{b}{yuan:.2f}\033[0m"

os.system('clear||cls')
while True:
    expr = input(">>> 金额表达式(或 q 退出):")
    if expr == "q": break
    try:
        result = Decimal(eval(expr, {"__builtins__": None}, {"Decimal": Decimal}))
        print(rainbow_money(result))
    except Exception as e:
        print(f"❌ 错误:{e}")

运行:python money_rainbow.py → 彩虹渐变金额!