我正在实现一个专门的哈希表。出于空间使用和性能原因,我正在尝试将大量数据存储在单个 64 位 int key 中。
每个键都应该有这样的结构:
// Key structure, from LSB
// eval result (16 bits)
// move (16 bits)
// age (16 bits): the move of the game on which this position would have occurred
// depth (8 bits)
// node type (8 bits): from the three constants above
这是一个简单的实现:
var keys [1000]uint64
var values [1000]uint64
func Put(b *dragontoothmg.Board, m dragontoothmg.Move, eval int16, depth uint8, ntype uint8) {
var value uint64 = uint64(eval) | (uint64(m) << 16) | (uint64(b.Fullmoveno) << 32) |
(uint64(depth) << 48) | (uint64(ntype) << 56)
hash := b.Hash()
key := hash ^ value
index := hash % uint64(len(keys))
keys[index] = key
values[index] = value
}
func Get(b *dragontoothmg.Board) (found bool, move dragontoothmg.Move,
eval int16, depth uint8, ntype uint8) {
hash := b.Hash()
index := hash % uint64(len(keys))
key := keys[index]
value := values[index]
found = (hash == (key ^ value))
if !found {
return false, 0, 0, 0, 0
}
eval = int16(value & 0xFFFF)
move = dragontoothmg.Move((value >> 16) & 0xFFFF)
depth = uint8((value >> 48) & 0xFF)
ntype = uint8((value >> 56) & 0xFF)
return
}
但是,当我尝试 Get() 数据时,返回的数据已损坏。我怀疑这可能与 eval 是一个带符号的 int,并且转换将其转换为带符号的 uint64 这一事实有关。我做错了什么,我该如何解决?
这是失败的测试结果:
--- FAIL: TestSimpleTt (0.10s)
transtable_test.go:37: Simple ttable test failed.
Put data: (board: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 0) e2e4 -30 6 2
Fetched data: true h8h8 -30 255 255
FAIL
h8h8 是字段的最大值,就其值(value)而言。
最佳答案
我无法在简化代码中重现您的结果 https://play.golang.org/p/shPN-1waZa :
func Pack(m, eval int16, depth, ntype uint8) (value uint64) {
value = (uint64(eval) |
(uint64(m) << 16) |
// (uint64(b.Fullmoveno) << 32) | <-- My suspicion is here !
(uint64(depth) << 48) |
(uint64(ntype) << 56))
return
}
func Unpack(value uint64) (move int16, eval int16, depth uint8, ntype uint8) {
eval = int16(value & 0xFFFF)
move = int16((value >> 16) & 0xFFFF)
depth = uint8((value >> 48) & 0xFF)
ntype = uint8((value >> 56) & 0xFF)
return
}
func main() {
m, e, d, n := int16(8), int16(8), uint8(8), uint8(8)
packedValue := Pack(m, e, d, n)
fmt.Printf("%v\n", packedValue)
move, eval, depth, ntype := Unpack(packedValue)
fmt.Printf("%v %v %v %v", move, eval, depth, ntype)
}
但我有怀疑:
a) dragonthooth.Move - 真的是int16吗?我想你有一组具有这种类型值的常量
b) 你正在打包 5 个值并提取 4 个。也许这不是错误,但检查 b.Fullmoveno 的类型是 int16 吗?
c) 我无法判断您其他代码的正确性。我只是希望你没有在散列、索引、键、值方面出错。
我不太明白你剩下的代码。
我想你的意思是 value structure 而不是 key structure(因为在你的代码中它是值包装的)
为什么要在单独的数组中定义 2 个键和值? 为什么不是 []{uint64,uint64}?甚至是 map[uint64]uint64?
关于转到哈希表 : casting without conversion?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43958297/
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat
我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>
查看我的Ruby代码:h=Hash.new([])h[0]=:word1h[1]=h[1]输出是:Hash={0=>:word1,1=>[:word2,:word3],2=>[:word2,:word3]}我希望有Hash={0=>:word1,1=>[:word2],2=>[:word3]}为什么要附加第二个哈希元素(数组)?如何将新数组元素附加到第三个哈希元素? 最佳答案 如果您提供单个值作为Hash.new的参数(例如Hash.new([]),完全相同的对象将用作每个缺失键的默认值。这就是您所拥有的,那是你不想要的。您可以改用
假设我有一个在Ruby中看起来像这样的哈希:{:ie0=>"Hi",:ex0=>"Hey",:eg0=>"Howdy",:ie1=>"Hello",:ex1=>"Greetings",:eg1=>"Goodday"}有什么好的方法可以将它变成如下内容:{"0"=>{"ie"=>"Hi","ex"=>"Hey","eg"=>"Howdy"},"1"=>{"ie"=>"Hello","ex"=>"Greetings","eg"=>"Goodday"}} 最佳答案 您要求一个好的方法来做到这一点,所以答案是:一种您或同事可以在六个月后理解
我在搜索我的值是方法的散列时遇到问题。我只是不想运行plan_type与键匹配的方法。defmethod(plan_type,plan,user){foo:plan_is_foo(plan,user),bar:plan_is_bar(plan,user),waa:plan_is_waa(plan,user),har:plan_is_har(user)}[plan_type]end目前如果我传入“bar”作为plan_type,所有方法都会运行,我怎么能只运行plan_is_bar方法呢? 最佳答案 这个变体怎么样?defmethod
你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p
有什么区别:@attr[:field]=new_value和@attr.merge(:field=>new_value) 最佳答案 如果您使用的是merge!而不是merge,则没有区别。唯一的区别是您可以在合并参数中使用多个字段(意思是:另一个散列)。例子:h1={"a"=>100,"b"=>200}h2={"b"=>254,"c"=>300}h3=h1.merge(h2)putsh1#=>{"a"=>100,"b"=>200}putsh3#=>{"a"=>100,"b"=>254,"c"=>300}h1.merge!(h2)pu
因此,对于普通哈希,您可以使用它来获取key:hash.keys如何获取如下所示的多维哈希的第二维键:{""=>{"first_name"=>"test","last_name"=>"test_l","username"=>"test_user","title"=>"SalesManager","office"=>"test","email"=>"test@test.com"}}每个项目都是唯一的。所以我想从上面得到的键是:first_name,last_name,username,title,officeandemail 最佳答案
我正在尝试循环哈希数组。当我到达获取枚举器开始循环的位置时,出现以下错误:undefinedmethod`[]'fornil:NilClass我的代码如下所示:defextraireAttributs(attributsParam)classeTrouvee=falsescanTrouve=falseownerOSTrouve=falseownerAppTrouve=falseresultat=Hash.new(0)attributs=Array(attributsParam)attributs.eachdo|attribut|#CRASHESHERE!!!typeAttribut=a
这个问题在这里已经有了答案:HashsyntaxinRuby[duplicate](1个回答)关闭5年前。我有一个Recipe,其中包含以下未通过lint测试的代码:service'apache'dosupports:status=>true,:restart=>true,:reload=>trueend失败并出现错误:UsethenewRuby1.9hashsyntax.supports:status=>true,:restart=>true,:reload=>true不确定新语法是什么样的...有人可以帮忙吗?