标题: Python大数存放格式 创建: 2023-03-17 20:20 更新: 2023-03-21 14:02 链接: https://scz.617.cn/python/202303172020.txt 获取大数的地址,一正一负 python3-dbg >>> x=3215031751 >>> hex(id(x)) '0x7f466c804bc0' >>> x=-3215031751 >>> hex(id(x)) '0x7f466c804e40' 在gdb中查看大数 gdb -q -nx -x gdbinit_x64.txt -x gdbhelper.py -p $(pidof python3-dbg) (gdb) p/x *(PyLongObject *)0x7f466c804bc0 $2 = { ob_base = { ob_base = { ob_refcnt = 0x1, ob_type = 0x9af720 }, ob_size = 0x2 }, ob_digit = { [0x0] = 0x3fa17dc7 } } (gdb) p/x ((PyLongObject *)0x7f466c804bc0)->ob_digit@2 $3 = { [0x0] = { [0x0] = 0x3fa17dc7 }, [0x1] = { [0x0] = 0x2 } } Python解释器内部以"2**30"进制存放大数,ob_size的绝对值表示有多少个系数, ob_size的符号对应大数的符号,ob_size为负时表示大数为负,ob_digit[]以 little-endian序存放ABS(ob_size)个系数。 下例是负数 (gdb) p/x *(PyLongObject *)0x7f466c804e40 $4 = { ob_base = { ob_base = { ob_refcnt = 0x1, ob_type = 0x9af720 }, ob_size = 0xfffffffffffffffe }, ob_digit = { [0x0] = 0x3fa17dc7 } } (gdb) p/x ((PyLongObject *)0x7f466c804e40)->ob_digit@(-(signed long long)0xfffffffffffffffe) (gdb) p/x ((PyLongObject *)0x7f466c804e40)->ob_digit@2 $5 = { [0x0] = { [0x0] = 0x3fa17dc7 }, [0x1] = { [0x0] = 0x2 } } -------------------------------------------------------------------------- def show_coefficient ( large, base ) : coefficient = [] while large > 0 : large, digit = divmod( large, base ) coefficient.append( hex( digit ) ) # # end of while # return coefficient[::-1] if coefficient else ['0x0'] # # end of show_coefficient # -------------------------------------------------------------------------- >>> show_coefficient( 3215031751, 2**30 ) ['0x2', '0x3fa17dc7'] Python序列化大数时没有用"2**30"进制,用的是"2**15"进制,pyc中TYPE_LONG型以 ushort[]存放"2**15"进制的系数。 >>> show_coefficient( 3215031751, 2**15 ) ['0x2', '0x7f42', '0x7dc7'] >>> hex(0xf*(2**15)**4+0x7fff*(2**15)**3+0x7fff*(2**15)**2+0x7fff*(2**15)**1+0x7fff) '0xffffffffffffffff' >>> show_coefficient( 0xffffffffffffffff, 2**15 ) ['0xf', '0x7fff', '0x7fff', '0x7fff', '0x7fff']