http://ericlippert.com/2013/11/14/a-practical-use-of-multiplicative-inverses/
大概就是需要三個數字,MAX[int] & 質數A[int:coprime] & inverse(MAX & 質數A)[int:coprime],最後一個數字可以算出來,MAX則為需求,類似99999999,質數A就到處亂找了,類似2147483647 (2^32 - 1)
so~ 以上,先列出inverse的寫法
http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
MAX = 99999999
COPRIME = 2147483647
def inverse(a, n)
t = 0 ; newt = 1
r = n ; newr = a
while newr != 0
quotient = r / newr
t , newt = newt , t - quotient * newt
r , newr = newr , r - quotient * newr
end
return "a is not invertible" if r > 1
return t < 0 ? t + n : t
end
COPRIME_INVERSE = inverse(COPRIME , MAX) #=> 52892335
再來其實就是使用了,使用的話就非常簡單,類似
def source_encode(source)
return source.to_i * COPRIME % MAX
end
def source_decode(source)
return source.to_i * COPRIME_INVERSE % MAX
end
source_encode(1) #=> 47483668
#...
當然你可以用小數字去測試這是否是正確的,類似 MAX = 10
MAX = 10
COPRIME = 2147483647
COPRIME_INVERSE = inverse(COPRIME , MAX) #=> 3
(MAX * 2).times do |source|
puts "#{source} : #{source_encode(source)} : #{source_decode(source_encode(source))}"
end
#=> 0 : 0 : 0
#=> 1 : 7 : 1
#=> 2 : 4 : 2
#=> 3 : 1 : 3
#=> 4 : 8 : 4
#=> 5 : 5 : 5
#=> 6 : 2 : 6
#=> 7 : 9 : 7
#=> 8 : 6 : 8
#=> 9 : 3 : 9
#=> 10 : 0 : 0
#=> 11 : 7 : 1
#=> 12 : 4 : 2
#=> 13 : 1 : 3
#=> 14 : 8 : 4
#=> 15 : 5 : 5
#=> 16 : 2 : 6
#=> 17 : 9 : 7
#=> 18 : 6 : 8
#=> 19 : 3 : 9
這邊其實多了示範在 MAX * 2 在顯示如果超過會怎樣,你會發現會循環,其實某種程度上這非常方便,類似前面再加上英文字母就可以多軌同時進行且自動切割好好,而如果你怕人破解,請隨機找個質數之類的,會建議大點,anyway以上 & (rock)
沒有留言:
張貼留言