Skip to content

标题: 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序列化大数时没有用"230"进制,用的是"215"进制,pyc中TYPE_LONG型以 ushort[]存放"2**15"进制的系数。

show_coefficient( 3215031751, 2**15 ) ['0x2', '0x7f42', '0x7dc7']

hex(0xf(215)4+0x7fff(215)3+0x7fff(215)2+0x7fff(215)1+0x7fff) '0xffffffffffffffff'

show_coefficient( 0xffffffffffffffff, 2**15 ) ['0xf', '0x7fff', '0x7fff', '0x7fff', '0x7fff']