python3解决位移溢出

本文探讨Python与JavaScript在位移运算上的不同,特别是在32位整数溢出处理上的区别。Python的int类型不会溢出,而JS则会截断。文中提供了一个Python函数int_overflow(val),用于模拟32位整数溢出效果,并实现了一个无符号右移函数unsigned_right_shift(n, i),用以匹配JS的>>>操作。

在观看该文章前,读者先可以看看这篇文章,清晰明了的介绍了位移的操作:https://www.cnblogs.com/yx729315991/p/6387711.html

因为要将js的一个签名算法移植到python上,遇到一些麻烦。
int无限宽度,不会溢出
算法中需要用到了32位int的溢出来参与运算,但是python的int是不会溢出的,达到界限后会自己转为long,所以很麻烦。

#使用-342686650:
ret = 123456789 << 20
print(ret)
得到结果129453825982464
print(bin(ret))
这个二进制是11101011011110011010001010100000000000000000000
明显已经超出32位了

在JS上
document.writeln(123456789 << 20);
得到结果是-783286272
这就是溢出后截取的,

在python上想实现溢出效果,找到一个函数
#这个函数可以得到32位int溢出结果,因为python的int一旦超过宽度就会自动转为long,永远不会溢出,有的结果却需要溢出的int作为参数继续参与运算
def int_overflow(val):
    maxint = 2147483647
    if not -maxint-1 <= val <= maxint:
        val = (val + (maxint + 1)) % (2 * (maxint + 1)) - maxint - 1
    return val


ret = int_overflow(123456789 << 20)
print(ret)
print(bin(ret))
现在得到结果是-783286272
二进制:-101110101100000000000000000000

负数使用无符号右移>>>
在JS中,可以使用 a>>>b来实现无符号位移,python中没有这个运算符,只能自己实现了

无符号右移>>>,就是将有符号int a和b转为无符号uint后,再进行普通右移>>运算

比如-1的有符号int就是-1,无符号int就是4294967295

我们自己实现>>>可以这样
#无符号右移
import ctypes
def unsigned_right_shitf(n,i):
    # 数字小于0,则转为32位无符号uint
    if n<0:
        n = ctypes.c_uint32(n).value
    # 正常位移位数是为正数,但是为了兼容js之类的,负数就右移变成左移好了
    if i<0:
        return -int_overflow(n << abs(i))
    #print(n)
    return int_overflow(n >> i)

ret = unsigned_right_shitf(-1,20)
print(ret)

结果等于4095
和JS上执行 -1 >>> 20 一样。

本文转载自:https://www.jianshu.com/p/24d11ab44ae6

整数溢出通常发生在对整数进行赋值或算术运算时,因操作结果超出了该整数类型所能表示的范围。下面从不同编程语言的角度介绍整数溢出的实现方法。 ### C语言实现整数溢出 在C语言中,整数溢出分为无符号整型溢出和有符号整型溢出。 #### 无符号整型溢出 无符号整型溢出时,结果会对该类型能表示的最大值加1取模。 ```c #include <stdio.h> int main() { unsigned int max = 0xFFFFFFFF; // 无符号整型的最大值 unsigned int result = max + 1; printf("max + 1 = %u\n", result); // 输出结果为0 return 0; } ``` #### 有符号整型溢出 有符号整型溢出的行为是未定义的,但在大多数编译器中,会发生回绕现象。 ```c #include <stdio.h> int main() { int max = 0x7FFFFFFF; // 有符号整型的最大值 int result = max + 1; printf("max + 1 = %d\n", result); // 输出结果为-2147483648 return 0; } ``` ### Java实现整数溢出 在Java中,一个`int`型变量占32位,能表示的数据范围为 -2&sup3;¹~2&sup3;¹ - 1之间的整数。当发生溢出时,编译器通常不会报错。 ```java public class IntegerOverflow { public static void main(String[] args) { int max = Integer.MAX_VALUE; // 整型的最大值 int result = max + 1; System.out.println("max + 1 = " + result); // 输出结果为-2147483648 } } ``` ### Python实现整数溢出Python 2时代,整型有`int`类型和`long`长整型,长整型不存在溢出问题。在Python 3后,统一使用了长整型,不会发生溢出。不过可以模拟溢出的效果。 ```python import ctypes # 模拟有符号32位整数溢出 max_int = 2**31 - 1 result = ctypes.c_int32(max_int + 1).value print(f"max + 1 = {result}") # 输出结果为-2147483648 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值