标题说明了这一点,Ruby中'some random string'.hash
可以返回的最大值是什么?
docs没有提供太多见解。
答案 0 :(得分:2)
可输出的最大尺寸String#hash
似乎是您环境中unsigned long
的最大尺寸。
String#hash
功能在rb_str_hash()
中实现:
/* string.c, l. 2290 */
st_index_t
rb_str_hash(VALUE str)
{
int e = ENCODING_GET(str);
if (e && rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
e = 0;
}
return rb_memhash((const void *)RSTRING_PTR(str), RSTRING_LEN(str)) ^ e;
}
st_index_t
定义为类型st_data_t
:
/* st.h, l. 48 */
typedef st_data_t st_index_t;
st_data_t
是unsigned long
:
/* st.h, l. 20 */
typedef unsigned long st_data_t;
由于散列是随机生成的(使用SipHash),因此unsigned long
中可能的整个值范围都应该可用。在64位环境中,unsigned long
当然是64位。 SipHash的输出是64位,因此在32位环境中,Ruby将其输出存储在一个带有两个32位无符号整数的数组中,rb_memhash()
将它们与按位异或组合。
/* siphash.h, l. 14 */
#ifndef HAVE_UINT64_T
typedef struct {
uint32_t u32[2];
} sip_uint64_t;
#define uint64_t sip_uint64_t
#else
typedef uint64_t sip_uint64_t;
#endif
/* random.c, l. 1306 */
st_index_t
rb_memhash(const void *ptr, long len)
{
sip_uint64_t h = sip_hash24(sipseed.key, ptr, len);
#ifdef HAVE_UINT64_T
return (st_index_t)h;
#else
return (st_index_t)(h.u32[0] ^ h.u32[1]);
#endif
}
这是Ruby的sip_hash24()
,如果你想看一下这个实现。
答案 1 :(得分:1)
Object#hash
method返回a Fixnum
,其中:
保存可以在本机机器字(减1位)中表示的整数值。
令人讨厌的是,似乎没有一种简单的方法可以确定特定系统的确切最大值(有一个open feature request by Matz - #7517),所以你必须自己计算它。
下面的示例代码(https://stackoverflow.com/a/736313/244128)适用于某些Ruby平台,但不能在所有这些平台上可靠地运行:
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
FIXNUM_MIN = -(2**(0.size * 8 -2))