2013-05-08 2 views
1

Я использую levigo, привязки leveldb для Go. Мои ключи: int64 и их нужно сортировать. По умолчанию, leveldb использует bytewise compator, поэтому я пытаюсь использовать varint-кодирование.по аналогии сравнить varint encoded int64's

func i2b(x int64) []byte { 
    b := make([]byte, binary.MaxVarintLen64) 
    n := binary.PutVarint(b, x) 
    return key[:n] 
} 

Мои ключи сортируются некорректно. В качестве теста я написал следующее.

var prev int64 = 0 
for i := int64(1); i < 1e5; i++ { 
    if bytes.Compare(i2b(i), i2b(prev)) <= 0 { 
     log.Fatalf("bytewise: %d > %d", b2i(prev), i) 
    } 
    prev = i 
} 

выход:bytewise: 127 > 128

playground

Я не уверен, где проблема. Я неправильно делаю кодирование? Является ли varint неправильной кодировкой?

РЕДАКТИРОВАТЬ:

BigEndian фиксированной кодирования ширина побайтно сравнимой

func i2b(x int64) []byte { 
    b := make([]byte, 8) 
    binary.BigEndian.PutUint64(b, uint64(x)) 
    return b 
} 
+1

обратный 'ключ [: n]' перед возвратом даст правильный результат. Однако у меня нет объяснений, почему. – thwd

+0

@ Настоящая сущность? –

+0

Возможно, вы правы – thwd

ответ

1

varint кодирования не побайтно сопоставимы * WRT порядку значений его кариеса. Один из вариантов, как написать упорядочения/сопоставляя функции (cmp сильфона), например,:

package main 

import (
     "encoding/binary" 
     "log" 
) 

func i2b(x int64) []byte { 
     var b [binary.MaxVarintLen64]byte 
     return b[:binary.PutVarint(b[:], x)] 
} 

func cmp(a, b []byte) int64 { 
     x, n := binary.Varint(a) 
     if n < 0 { 
       log.Fatal(n) 
     } 

     y, n := binary.Varint(b) 
     if n < 0 { 
       log.Fatal(n) 
     } 

     return x - y 
} 

func main() { 
     var prev int64 = 0 
     for i := int64(1); i < 1e5; i++ { 
       if cmp(i2b(i), i2b(prev)) <= 0 { 
         log.Fatal("fail") 
       } 
       prev = i 
     } 
} 

Playground

(*) Причина (также) бит fiddling performed.

+0

Есть ли кодировка, которая сохранит порядок базовых значений? –

+1

@iliacholy: Конечно, например, фиксированный размер с правильной консистенцией. Или, например. переменная длина с небольшим префиксом журнала (значения). Их можно изобретать бесконечно. Тем не менее, [u] varint-кодирование более экономично, чем все приведенные выше примеры, особенно для небольших чисел, которые встречаются довольно часто в реальных сценариях. – zzzz

Смежные вопросы