跳转至

Base 60 encoding of positive floating point numbers in IDL

原文链接: https://www.nv5geospatialsoftware.com/Learn/Blogs/Blog-Details/base-60-encoding-of-positive-floating-point-numbers-in-idl

18492 Rate this article:

3.5

Base 60 encoding of positive floating point numbers in IDL

Anonym Thursday, February 2, 2017

Here is an example of representing numbers efficiently using a restricted set of symbols. I am using a set of 60 symbols (or characters) to encode floating point numbers as strings of any selected length. The longer the strings are, the more precise the numbers will potentially be.

Here is an example of a representation, this is restricted to positive numbers, in order to keep the example short.

IDL> a=[14.33, 3.1415, 12345]

IDL> a

14.330000       3.1415000       12345.000

IDL> base60(a)

FotV*

FdiDx

HdzS*

IDL> base60(a, precision=8)

FotV**aO

FdiDx*^c

HdzS****

IDL> base60(base60(a)) - a

-4.5533356836102712e-006 -4.6258149324351905e-006    -0.016666666666424135

IDL> base60(base60(a, precision=8)) - a

-9.2104102122902987e-012 -4.6052051061451493e-013 -7.7159711509011686e-008

In this example, it can be seen that the 5-digit representations are not as close to the original numbers as the 8-digit representations.

The code example for the base60 function is listed below.

;

; Converts from a numeric type to a base 60 representation

; Converts from a base 60 string to a floating point representation

; PRECISION is only used to determine how many symbols to use when encoding,

; and is ignored for decoding.

function Base60, input, precision=precision

compile_opt idl2,logical_predicate

; set default precision of 5 digits for encoding only

if ~keyword_set(precision) then precision = 5

; base 60 symbology

symbols = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*'

base = strlen(symbols)

; fast conversion from symbol to value

lut = bytarr(256)

lut[byte(symbols)] = bindgen(base)

if isa(input, /string) then begin

; convert from base60 string to float

; find exponent first

scale = replicate(double(base),n_elements(input)) ^ $

(lut[byte(strmid(input,0,1))] - base/2)

res = dblarr(n_elements(input))

for i=max(strlen(input))-1,1,-1 do begin

dig = lut[byte(strmid(input,i,1))]

res += dig

res /= base

endfor

res *= scale

endif else begin

; convert from float to base60 strings

; encode exponent(scale) first

ex = intarr(n_elements(input))

arr = input

dbase = double(base)

repeat begin

dec = fix(arr ge 1)

ex += dec

arr *= dbase ^ (-dec)

inc = fix(arr lt 1/dbase)

ex -= inc

arr *= dbase ^ inc

endrep until array_equal(arr lt 1 and arr ge 1/dbase,1b)

if max(ex) ge base/2 || min(ex) lt -base/2 then begin

message, 'Number is outside representable range'

endif

bsym = byte(symbols)

res = string(bsym[reform(ex+base/2,1,n_elements(ex))])

for i=1,precision-1 do begin

arr *= base

fl = floor(arr)

arr -= fl

res += string(bsym[reform(fl,1,n_elements(fl))])

endfor

endelse

return, res

end

When Might I Use An IDL Task? IDL As a Key to Data Analysis in a Heterogeneous Computing Environment First Valley Shadow Detection