7 min read

使用Grok製作2025年所得稅試算

使用Grok製作2025年所得稅試算
grok_tax_20250412-pic1

馬上要到5月的繳稅季節了,我想要算一下我該繳多少稅,其實應該是要算該領多少股息時,我可以繳最低的稅。

我的薪資所得很好算(領固定月薪),兩季獎金也分別在2月、6月領(噓!!)

所以當我的薪資所得出來了,我再來配我領的股息可以多少~

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm

def calculate_income_tax():
    # 設置中文字型
    plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'Arial Unicode MS']
    plt.rcParams['axes.unicode_minus'] = False

    # 2024 年稅制參數(適用 2025 年申報)
    TAX_BRACKETS = [
        (590000, 0.05, 0),
        (1330000, 0.12, 41300),
        (2420000, 0.20, 147700),
        (4530000, 0.30, 389700),
        (float('inf'), 0.40, 842700)
    ]
    EXEMPTION_PER_PERSON = 97000  # 每人免稅額
    STANDARD_DEDUCTION_SINGLE = 131000  # 單身標準扣除額
    STANDARD_DEDUCTION_COUPLE = 262000  # 有配偶標準扣除額
    SALARY_DEDUCTION = 218000  # 薪資特別扣除額
    DEPENDENT_DEDUCTION = 97000  # 每位扶養人扣除額
    DIVIDEND_CREDIT_RATE = 0.085  # 股利抵減稅率
    DIVIDEND_CREDIT_CAP = 80000  # 股利抵減上限
    DIVIDEND_SEPARATE_TAX_RATE = 0.28  # 分離計稅股利稅率

    # 輸入資料(單位:萬元)
    print("=== 2025 年台灣所得稅計算器 ===")
    try:
        salary_wan = float(input("請輸入您的年薪資所得(萬元):"))
        dividend_wan = float(input("請輸入您的年股利所得(萬元):"))
        has_spouse = input("是否有配偶?(是:Y / 否:N):").strip().upper() == 'Y'
        dependents = int(input("請輸入扶養人數(不含配偶):"))
        
        # 將輸入的萬元轉換為元
        salary = salary_wan * 10000
        dividend = dividend_wan * 10000
    except ValueError:
        print("輸入格式錯誤,請輸入數字!")
        return

    # 計算扣除額
    exemption = EXEMPTION_PER_PERSON * (1 + (1 if has_spouse else 0) + dependents)
    standard_deduction = STANDARD_DEDUCTION_COUPLE if has_spouse else STANDARD_DEDUCTION_SINGLE
    salary_deduction = SALARY_DEDUCTION if salary > 0 else 0
    total_deductions = exemption + standard_deduction + salary_deduction

    # 計算基準稅額(股利 = 0)
    base_taxable_income = max(0, salary - total_deductions)
    base_tax = 0
    for bracket_limit, rate, progressive_diff in TAX_BRACKETS:
        if base_taxable_income <= bracket_limit:
            base_tax = base_taxable_income * rate - progressive_diff
            break
    base_tax = max(0, base_tax)

    # 方式一:合併計稅
    total_income = salary + dividend
    taxable_income = max(0, total_income - total_deductions)
    tax_merged = 0
    for bracket_limit, rate, progressive_diff in TAX_BRACKETS:
        if taxable_income <= bracket_limit:
            tax_merged = taxable_income * rate - progressive_diff
            break
    tax_merged = max(0, tax_merged)
    dividend_credit = min(dividend * DIVIDEND_CREDIT_RATE, DIVIDEND_CREDIT_CAP)
    tax_merged_final = max(0, tax_merged - dividend_credit)

    # 方式二:分離計稅(計算但不顯示在圖表中)
    salary_taxable_income = max(0, salary - exemption - standard_deduction - salary_deduction)
    tax_salary = 0
    for bracket_limit, rate, progressive_diff in TAX_BRACKETS:
        if salary_taxable_income <= bracket_limit:
            tax_salary = salary_taxable_income * rate - progressive_diff
            break
    tax_salary = max(0, tax_salary)
    tax_dividend = dividend * DIVIDEND_SEPARATE_TAX_RATE
    tax_separate_final = tax_salary + tax_dividend

    # 計算交叉點(合併計稅稅額 = 基準稅額)
    def find_intersection(salary, total_deductions, base_tax):
        x_intersection = None
        base_taxable_income = max(0, salary - total_deductions)
        
        for bracket_limit, rate, progressive_diff in TAX_BRACKETS:
            if base_taxable_income > bracket_limit:
                continue
            
            lower_bound = max(0, total_deductions - salary)
            upper_bound = bracket_limit - (salary - total_deductions)
            
            if x_intersection is None:
                coeff = rate - 0.085
                if coeff != 0:
                    x = (base_tax + progressive_diff - (salary - total_deductions) * rate) / coeff
                    if x >= lower_bound and x <= upper_bound and x * 0.085 <= 80000:
                        x_intersection = x
            
            if x_intersection is None:
                x = (base_tax + progressive_diff + 80000 - (salary - total_deductions) * rate) / rate
                if x >= lower_bound and x <= upper_bound and x * 0.085 > 80000:
                    x_intersection = x
        
        return x_intersection / 10000 if x_intersection is not None else None  # 轉回萬元

    x_intersection_wan = find_intersection(salary, total_deductions, base_tax)

    # 動態調整 X 軸範圍(根據輸入股利)
    max_dividend_wan = max(100, dividend_wan)  # 如果股利大於 100 萬,則以輸入股利為上限
    # 確保 X 軸上限為 10 萬的倍數
    max_dividend_wan = np.ceil(max_dividend_wan / 10) * 10

    # 繪製曲線圖(Y 軸單位為萬元,只顯示合併計稅)
    dividend_range_wan = np.linspace(0, max_dividend_wan, int(max_dividend_wan * 10) + 1)  # 每 0.1 萬一個點
    dividend_range = dividend_range_wan * 10000
    tax_merged_values = []

    for div in dividend_range:
        total_income = salary + div
        taxable_income = max(0, total_income - total_deductions)
        tax_merged = 0
        for bracket_limit, rate, progressive_diff in TAX_BRACKETS:
            if taxable_income <= bracket_limit:
                tax_merged = taxable_income * rate - progressive_diff
                break
        tax_merged = max(0, tax_merged)
        dividend_credit = min(div * DIVIDEND_CREDIT_RATE, DIVIDEND_CREDIT_CAP)
        tax_merged_values.append(max(0, tax_merged - dividend_credit) / 10000)  # 轉為萬元

    # 計算轉折點(稅率級距變化點)
    turning_points = []
    for bracket_limit, rate, progressive_diff in TAX_BRACKETS:
        div = bracket_limit - (salary - total_deductions)  # 股利(元)
        if div < 0:  # 如果股利為負,跳過
            continue
        if div / 10000 > max_dividend_wan:  # 如果股利超出圖表範圍,跳過
            break
        taxable_income = bracket_limit
        tax_merged = taxable_income * rate - progressive_diff
        tax_merged = max(0, tax_merged)
        dividend_credit = min(div * DIVIDEND_CREDIT_RATE, DIVIDEND_CREDIT_CAP)
        tax_value = max(0, tax_merged - dividend_credit) / 10000  # 轉為萬元
        turning_points.append((div / 10000, tax_value))  # (X, Y) 轉折點

    # 計算輸入股利所得的應繳稅額(Y 值)
    input_dividend_tax = tax_merged_final / 10000  # 轉為萬元

    plt.figure(figsize=(12, 10))
    plt.plot(dividend_range_wan, tax_merged_values, label='合併計稅', color='blue')
    plt.axhline(y=base_tax / 10000, color='green', linestyle='--', label=f'基準稅額 ({base_tax / 10000:,.1f} 萬)')
    if x_intersection_wan is not None and 0 <= x_intersection_wan <= max_dividend_wan:
        plt.axvline(x=x_intersection_wan, color='purple', linestyle='--', label=f'交叉點 (股利 {x_intersection_wan:.2f} 萬)')
        plt.text(x_intersection_wan, 0, f'{x_intersection_wan:.2f}', color='purple', ha='center', va='top', fontsize=10, bbox=dict(facecolor='white', alpha=0.8))
        plt.text(0, base_tax / 10000, f'{base_tax / 10000:,.1f}', color='green', ha='right', va='center', fontsize=10, bbox=dict(facecolor='white', alpha=0.8))

    # 標記轉折點
    for x, y in turning_points:
        plt.scatter(x, y, color='blue', s=50, zorder=5)  # 畫轉折點
        plt.text(x, -0.2, f'{x:.2f}', color='blue', ha='center', va='top', fontsize=10, bbox=dict(facecolor='white', alpha=0.8))
        plt.text(x + 2, y, f'{y:.1f}', color='blue', ha='left', va='center', fontsize=10, bbox=dict(facecolor='white', alpha=0.8))

    # 標記輸入的股利所得位置
    if 0 <= dividend_wan <= max_dividend_wan:  # 確保輸入的股利在圖表範圍內
        plt.axvline(x=dividend_wan, color='orange', linestyle='--', label=f'輸入股利 ({dividend_wan:.2f} 萬)')
        plt.scatter(dividend_wan, input_dividend_tax, color='orange', s=50, zorder=5)  # 畫輸入點
        plt.text(dividend_wan, 0, f'{dividend_wan:.2f}', color='orange', ha='center', va='top', fontsize=10, bbox=dict(facecolor='white', alpha=0.8))
        plt.text(dividend_wan + 2, input_dividend_tax, f'{input_dividend_tax:.1f}', color='orange', ha='left', va='center', fontsize=10, bbox=dict(facecolor='white', alpha=0.8))

    plt.xlabel('股利所得 (萬元)')
    plt.ylabel('應繳稅額 (萬元)')
    plt.title(f'薪資所得 {salary_wan:.0f} 萬 - 應繳稅額隨股利所得變化')
    plt.legend()
    plt.grid(True)
    plt.ylim(-0.5, max(max(tax_merged_values), base_tax / 10000) + 0.5)  # 調整 Y 軸範圍,僅考慮合併計稅
    plt.xticks(np.arange(0, max_dividend_wan + 10, 10))  # X 軸以每 10 萬為間距
    plt.show()

    # 輸出結果
    print("\n=== 計算結果 ===")
    print(f"薪資所得:{salary_wan:,.0f} 萬元 ({salary:,.0f} 元)")
    print(f"股利所得:{dividend_wan:,.0f} 萬 ({dividend:,.0f} 元)")
    print(f"配偶:{'有' if has_spouse else '無'}")
    print(f"扶養人數:{dependents} 人")
    print(f"總扣除額:{total_deductions:,.0f} 元(免稅額:{exemption:,.0f} 元,標準扣除額:{standard_deduction:,.0f} 元,薪資扣除額:{salary_deduction:,.0f} 元)")
    print(f"基準稅額(股利 = 0):{base_tax:,.0f} 元 ({base_tax / 10000:,.1f} 萬)")
    print("\n合併計稅:")
    print(f"  綜合所得淨額:{taxable_income:,.0f} 元")
    print(f"  應納稅額:{tax_merged:,.0f} 元")
    print(f"  股利抵減稅額:{dividend_credit:,.0f} 元")
    print(f"  應繳稅額:{tax_merged_final:,.0f} 元 ({tax_merged_final / 10000:,.1f} 萬)")
    print("\n分離計稅:")
    print(f"  薪資所得淨額:{salary_taxable_income:,.0f} 元")
    print(f"  薪資稅額:{tax_salary:,.0f} 元")
    print(f"  股利稅額:{tax_dividend:,.0f} 元")
    print(f"  應繳稅額:{tax_separate_final:,.0f} 元 ({tax_separate_final / 10000:,.1f} 萬)")
    print("\n交叉點:")
    if x_intersection_wan is not None:
        print(f"當股利所得為 {x_intersection_wan:.2f} 萬時,合併計稅稅額等於基準稅額 {base_tax:,.0f} 元 ({base_tax / 10000:,.1f} 萬)")
    else:
        print("未找到交叉點(可能因稅率級距或抵減上限)")
    print("\n建議選擇:", end="")
    if tax_merged_final <= tax_separate_final:
        print(f"合併計稅,應繳稅額 {tax_merged_final:,.0f} 元 ({tax_merged_final / 10000:,.1f} 萬)")
    else:
        print(f"分離計稅,應繳稅額 {tax_separate_final:,.0f} 元 ({tax_separate_final / 10000:,.1f} 萬)")

# 執行程式
if __name__ == "__main__":
    calculate_income_tax()

這個程式主要功能有:

1.輸入薪資所得

2.輸入股利所得

3.有無配偶

4.扶養人數(不含配偶)

5.會匯出一個應繳稅額與股利所得的曲線圖。

我輸入薪資所得100萬、股利30萬、有配偶、扶養人數零,輸出結果與曲線圖如下:

=== 計算結果 ===
薪資所得:100 萬元 (1,000,000 元)
股利所得:30 萬 (300,000 元)
配偶:有
扶養人數:0 人
總扣除額:674,000 元(免稅額:194,000 元,標準扣除額:262,000 元,薪資扣除額:218,000 元)
基準稅額(股利 = 0):16,300 元 (1.6 萬)

合併計稅:
綜合所得淨額:590,000 元
應納稅額:29,500 元
股利抵減稅額:22,440 元
應繳稅額:8,320 元 (0.8 萬)

分離計稅:
薪資所得淨額:326,000 元
薪資稅額:16,300 元
股利稅額:84,000 元
應繳稅額:100,300 元 (10.0 萬)

交叉點:
當股利所得為 -0.00 萬時,合併計稅稅額等於基準稅額 16,300 元 (1.6 萬)

建議選擇:合併計稅,應繳稅額 8,320 元 (0.8 萬)

可以看到:我的稅只要繳8320,同時也可以看到,當我的股利為26.4萬時,我要繳7000元的稅。

這程式還不賴吧~!

好了,我要去湊我的股利了。