① 一句话架构:金额系统 4 层模型 🏗️
| 层级 | 技术 | 精度 | 示例 |
|---|---|---|---|
| 存储层 | int 分厘 | 0 误差 | price = 12345 # 123.45 元 |
| 计算层 | Decimal | 用户指定 | Decimal('123.45') |
| 展示层 | str 格式化 | 2 位小数 | ¥123.45 |
| 导出层 | CSV/Excel | 2 位小数 | 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}m¥{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}m¥{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→ 彩虹渐变金额!