在测试HIVE API的时候,发现要想使其中的一个API按着预想中的情况正确工作,需要传入int64_t类型的最大值,你要说什么8位、16位的最大值,我也许张口就来,可以64位我的大脑也处理不过来啊。
(图源 :pixabay)
基本原理
HIVE代码中直接用的是std::numeric_limits< int64_t >::max()
,我也没法直接引用呀。
那64位最大值是多少呢?我们知道,计算机中的数都是以二进制形式表示,所谓多少位就是多少个0和1,比如64位就是64个0、1组合。
而有符号数最高位用来表示符号位,符号位为0表示正数,符号位为1表示负数,其它数位用补码的形式表示:
正数的补码就是其二进制表示,与原码相同;负数的补码就是除符号位外的所有位取反后加1。
代码计算
知道了这些,那么求不同位数的数的最大正值就很容易了,比如我可以根据上述信息写出如下函数:
其实就是计算二进制函数的10进制值,因为正数补码和源码相同,那么int64_t最大值其实就是63个1组成的二进制数。
我们来测试并计算一下:
看来9223372036854775807
就是我们想要的结果。
使用ctypes
为了计算一个数值,写了一堆垃圾代码,我觉得我有点傻,那是不是有更简便的方法呢?我找到一种也许不算是简便方法的方法,那就是使用ctypes
ctypes能做很多事情,不过我想让它做的就是在python中使用c语言的类型,比如int64,而我们根据上述分析不难得出,int64最大值就是uint64最大值减1再除以2。
所以我们可以利用如下代码计算int64的最大值:
对比不难发现,和我们之前计算的结果完全一致。
移位计算
其实还有一种更简单的方法就是移位计算法,int64的最大值是63个1组成的2进制数,那么怎么能得到这个二进制数呢?
我们知道1个1组成的2进制数,是可以通过二进制数10减去二进制数1来获取,那么63个1组成的二进制数,其实也可以用10000(63个零)组成的64位二进制数减1来获取,而1后边63个零,就是把1左移了63位。
代码也超级简单:
到底用啥?
尽管我制造出三种超级复杂的计算方法,但是我觉得很傻,不就是一个数嘛,直接引用9223372036854775807
就好了呗?
可是在代码中引用这个数我又觉得很不优雅,哪怕我可以做类似如下定义:
MAX_INT64_VALUE = 9223372036854775807
我估计以后我会忍不住问自己,这个9223372036854775807
哪里来的呢?
想了好久之后突然想起来,我是不是太傻了,十六进制数就是二进制数的便于阅读的表示嘛,那么INT64的最大值,那不就是0x7FFFFFFFFFFFFFFF
嘛(最高位不等于1),所以代码中直接用以下定义即可:
MAX_INT64_VALUE = 0x7FFFFFFFFFFFFFFF
既含义明确,又不会有疑问,看起来又很优雅。
补充
网上还有代码计算int类型最大值,使用sys.max_size,在64位主机上代码可以得出正确的值。
但是在32位系统上,算出的值就是int32_t的最大值了。
所以在我们的程序中使用这种对系统依赖程度高的代码,是行不通的。
相关链接
- 补码
- https://docs.python.org/3.6/library/ctypes.html
- https://en.cppreference.com/w/cpp/types/numeric_limits/max
This page is synchronized from the post: ‘每天进步一点点:Python 中int64_t的最大值?’