You need to enable JavaScript to run this app. Python结合SQLite建表实现蒙特卡洛求π时触发类型转换报错
优惠活动
大模型
产品
解决方案
定价
更多

Python结合SQLite建表实现蒙特卡洛求π时触发类型转换报错

报错原因定位

你遇到的报错核心是首次运行的判断逻辑完全失效,具体逻辑链是:

  • SQLite 执行SELECT MAX(字段)查询空表时,不会返回空结果,而是返回一个包含None的元组,比如查询Pi表的最大parses值,空表时cur.fetchone()会得到(None,),而不是Python层面的None值
  • 你写的判断条件if parses is None:永远不会命中,哪怕Pi表是全新的空表,代码也会强行走到else分支
  • 进入else分支后查询MAX(incircle),拿到的列值是None,直接转成int就会抛出你看到的类型错误
  • 除此之外还有两处连带的逻辑bug,就算解决了当前报错,后续运行也会触发其他异常:
    • 插入XY表时,直接把x、y的浮点数值传给了x_id/y_id这两个整型字段,字段类型不匹配
    • Pi表给incircle字段加了UNIQUE约束,后续累计计算时如果数值和历史记录重复,会被INSERT OR IGNORE直接跳过,无法保存新的计算结果
针对性修改步骤

1. 修正空表判断逻辑,直接解决当前报错

替换原来的历史值查询和分支判断部分代码:

# 一次性查询历史累计的总点数、圆内点数,避免重复查库
cur.execute('''SELECT MAX(parses), MAX(incircle) FROM Pi''')
# 空表时返回的是(None, None),不是None本身
max_total, max_circle = cur.fetchone()

runs = input('Enter number of points: ')
print('***Started calculating***')
n = int(runs)

# 修正判断条件:判断列值是否为None,而不是判断fetch的结果是否为None
if max_total is None:
    num_point_circle = 0
    num_point_total = 0
    print('###STARTING FROM SCRATCH###')
else:
    num_point_circle = int(max_circle)
    num_point_total = int(max_total)
    print(f'###CONTINUE FROM {num_point_total} PARSES###')

2. 修正XY表的字段赋值逻辑

原来的代码错误地把x、y的数值直接传给了存自增ID的整型字段,替换循环内的插入逻辑:

try:
    for i in range(n):
        x = random.uniform(0, 1)
        y = random.uniform(0, 1)
        # 插入x值到X表
        cur.execute('INSERT OR IGNORE INTO X (x_value) VALUES (?)', (x,))
        # 不管是新插入还是已存在的x值,查询对应的X表id
        cur.execute('SELECT id FROM X WHERE x_value = ?', (x,))
        x_id = cur.fetchone()[0]

        # 同理处理y值
        cur.execute('INSERT OR IGNORE INTO Y (y_value) VALUES (?)', (y,))
        cur.execute('SELECT id FROM Y WHERE y_value = ?', (y,))
        y_id = cur.fetchone()[0]

        distance = x**2 + y**2
        if distance <= 1:
            num_point_circle += 1
            loc = 'Inside Circle'
        else:
            loc = 'Outside Circle'
        # 用查询到的id插入XY表
        cur.execute('INSERT OR IGNORE INTO XY (x_id, y_id, loc) VALUES (?,?,?)', (x_id, y_id, loc))

        num_point_total += 1

3. 调整Pi表的约束定义

去掉incircle字段不必要的UNIQUE约束,避免后续累计值重复时被跳过插入:

cur.execute('''CREATE TABLE IF NOT EXISTS Pi
(id INTEGER PRIMARY KEY, pi_value REAL, Accuracy FLOAT, parses INTEGER,
incircle INTEGER)''')

4. 收尾优化

在代码所有逻辑执行完毕后,加一行数据库关闭语句,避免出现SQLite文件锁的问题:

conn.close()

内容的提问来源于stack exchange,提问作者Tvergos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.05 02:06:08