Binary coded decimal: Difference between revisions

julia example
m (→‎{{header|J}}: grammar)
(julia example)
Line 115:
25
NB. ...</lang>
 
 
=={{header|Julia}}==
Handles negative and floating point numbers (but avoid BigFloats due to very long decimal places from binary to decimal conversion).
<lang ruby>const nibs = [0b0, 0b1, 0b10, 0b11, 0b100, 0b101, 0b110, 0b111, 0b1000, 0b1001]
 
"""
function bcd_decode(data::Vector{codeunit}, sgn, decimalplaces; table = nibs)
 
Decode BCD number
bcd: packed BCD data as vector of bytes
sgn: sign(positive 1, negative -1, zero 0)
decimalplaces: decimal places from end for placing decimal point (-1 if none)
table: translation table, defaults to same as nibble (nibs table)
"""
function bcd_decode(bcd::Vector{UInt8}, sgn, decimalplaces = 0; table = nibs)
decoded = 0
for (i, byt) in enumerate(bcd)
decoded = decoded * 10 + table[byt >> 4 + 1]
decoded = decoded * 10 + table[byt & 0b1111 + 1]
end
return decimalplaces == 0 ? sgn * decoded : sgn * decoded / 10^decimalplaces
end
 
"""
function bcd_encode(number::Real; table::Vector{UInt8} = nibs)
 
Encode real number as BCD.
`number`` is in native binary formats
`table`` is the table used for encoding the nibbles of the decimal digits, default `nibs`
Returns: BCD encoding vector of UInt8, number's sign (1, 0 -1), and position of decimal point
"""
function bcd_encode(number::Real; table::Vector{UInt8} = nibs)
if (sgn = sign(number)) < 0
number = -number
end
s = string(number)
if (exponentfound = findlast(ch -> ch in ['e', 'E'], s)) != nothing
expplace = parse(Int, s[exponentfound+1:end])
s = s[begin:exponentfound-1]
else
expplace = 0
end
if (decimalplaces = findfirst(==('.'), s)) != nothing
s = s[begin:decimalplaces-1] * s[decimalplaces+1:end]
decimalplaces = length(s) - decimalplaces + 1
decimalplaces -= expplace
else
decimalplaces = -expplace
end
len = length(s)
if isodd(len)
s = "0" * s
len += 1
end
return [table[s[i+1]-'0'+1] | (table[s[i]-'0'+1] << 4) for i in 1:2:len-1], sgn, decimalplaces
end
 
"""
function bcd_encode(number::Integer; table::Vector{UInt8} = nibs)
 
Encode integer as BCD.
`number`` is in native binary formats
`table`` is the table used for encoding the nibbles of the decimal digits, default `nibs`
Returns: Tuple containg two values: a BCD encoded vector of UInt8 and the number's sign (1, 0 -1)
"""
function bcd_encode(number::Integer; table::Vector{UInt8} = nibs)
if (sgn = sign(number)) < 0
number = -number
end
s = string(number)
len = length(s)
if isodd(len)
s = "0" * s
len += 1
end
return [table[s[i+1]-'0'+1] | (table[s[i]-'0'+1] << 4) for i in 1:2:len-1], sgn
end
 
 
for test in [1, 2, 3, -9876, 10, 12342436]
enc = bcd_encode(test, table = nibs)
dec = bcd_decode(enc..., table = nibs)
println("$test encoded is $enc, decoded is $dec")
end
 
for test in [-987654.321, -10.0, 9.9999, 123424367.0089]
enc = bcd_encode(test, table = nibs)
dec = bcd_decode(enc..., table = nibs)
println("$test encoded is $enc, decoded is $dec")
end
</lang>{{out}}
<pre>
1 encoded is (UInt8[0x01], 1), decoded is 1
2 encoded is (UInt8[0x02], 1), decoded is 2
3 encoded is (UInt8[0x03], 1), decoded is 3
-9876 encoded is (UInt8[0x98, 0x76], -1), decoded is -9876
10 encoded is (UInt8[0x10], 1), decoded is 10
12342436 encoded is (UInt8[0x12, 0x34, 0x24, 0x36], 1), decoded is 12342436
-987654.321 encoded is (UInt8[0x09, 0x87, 0x65, 0x43, 0x21], -1.0, 3), decoded is -987654.321
-10.0 encoded is (UInt8[0x01, 0x00], -1.0, 1), decoded is -10.0
9.9999 encoded is (UInt8[0x09, 0x99, 0x99], 1.0, 4), decoded is 9.9999
1.234243670089e8 encoded is (UInt8[0x01, 0x23, 0x42, 0x43, 0x67, 0x00, 0x89], 1.0, 4), decoded is 1.234243670089e8
</pre>
 
 
=={{header|Pascal}}==
Line 156 ⟶ 261:
99*99 =9801
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-check}}
4,105

edits