Juliasta löytyy 8, 16, 32 ja 64-bittiset datatyypit kuten muistakin ohjelmointikelistä. Lisäksi löytyvät merkkijonot ja binääri- sekä heksaesitysmuodot. Käyn tässä kirjoituksessa läpi joitakin tyyppimuunnoksia jotka tulevat joissakin yhteyksissä vastaan mutta eivät ole aivan ilmeisiä.
Tarkastelen tässä hieman tavanomaisesta poikkeavia tyyppikonversioita Julian tyyppien välillä.
Kokonaislukujen konversio bittijonoksi onnistuu bitstring
-komennolla:
= UInt8(123) l
0x7b
= bitstring(l) b
"01111011"
Takaisin päin päästään parse
-komennolla:
= parse(UInt8, b, base=2) l
0x7b
Hieman harvemmin käytetyt operaatiot <<
ja >>
voivat olla melko käteviä toisinaan. Ne siirtävät luvun bittejä oikealle tai vasemmalle:
= bitstring(UInt8(123) << 1) l1
"11110110"
= bitstring(UInt8(123) >> 1) l2
"00111101"
Näiden konversio takaisin kokonaisluvuiksi:
UInt8, l1, base=2) * 1 parse(
246
UInt8, l2, base=2) * 1 parse(
61
Left shift siis tuplaa kokonaisluvun ja right shift puolittaa sen, ns. integer division.
123, 2) == 123 >> 1 div(
true
Ohjelmointikielissä kokonaisluku ja liukuluku ovat täysin eri asioita, vaikka niitä voikin sekoittaa keskenään. Esimerkiksi lukujen 1 ja 1.0 binääriesitykset 16-bittisella aritmetiikalla:
= Float16(1.0)
f1 = Int16(1)
l1 , l1 f1
(Float16(1.0), 1)
= bitstring(f1)
b1 = bitstring(l1)
b2 , b2 b1
("0011110000000000", "0000000000000001")
Jos lasketaan 1 + 1.0
, pitää kokonaisluku ensin muuttaa liukuluvuksi. Nämä binääriesitykset voidaan taas parse
-komennolla muuttaa 16-bittisiksi kokonaisluvuiksi:
= parse(Int16, b1, base=2)
m = parse(Int16, b2, base=2)
n , n m
(15360, 1)
Tässä m
on nyt liukuluku 1.0, tosin väärässä tyypissä. Se voidaan tulkita uudelleen liukuluvuksi reinterpret
-komennolla:
= reinterpret(Float16, m) f2
Float16(1.0)
Bittitason manipulointiin päästään muuntamalla binääriesitys vaikkapa boolean-vektoriksi:
= [b == '1' for b in b1]
bits ' bits
1×16 LinearAlgebra.Adjoint{Bool,Array{Bool,1}}:
0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0
https://en.wikipedia.org/wiki/Half-precision_floating-point_format
sign 1 bit, exponent 5 bit, fraction 10 bit
ASCII-merkkijonot voidaan esittää 8-bittisillä unsigned integer tyypeillä. Näin nämä on tyypillisesti tallennettu tiedostoformaateissa.
= Vector{UInt8}("Hello, world!")
s s
13-element Array{UInt8,1}:
0x48
0x65
0x6c
0x6c
0x6f
0x2c
0x20
0x77
0x6f
0x72
0x6c
0x64
0x21
Konversio merkkijonoksi tapahtuu String
-komennolla:
String(s)
"Hello, world!"
Merkkijonon muuttaminen kokonaisluvuksi tapahtuu niin, että ensin tehdään heksadesimaaliesitys bytes2hex
-funktiolla jonka jälkeen parsitaan BigInt
-tyypiksi parse
-komennolla:
= Vector{UInt8}("Hello, world!")
s = bytes2hex(s) h
"48656c6c6f2c20776f726c6421"
= parse(BigInt, h, base=16) l
5735816763073854953388147237921
Toiseen suuntaan mennään muuntamalla BigInt
ensin heksadesimaaliesitysmuotoon jonka jälkeen hex2bytes
-funktiolla takaisin Vector{UInt8}
-tyypiksi josta edelleen merkkijonoksi:
= string(l, base=16) l2
"48656c6c6f2c20776f726c6421"
= hex2bytes(l2)
l3 ' l3
1×13 LinearAlgebra.Adjoint{UInt8,Array{UInt8,1}}:
0x48 0x65 0x6c 0x6c 0x6f 0x2c 0x20 0x77 0x6f 0x72 0x6c 0x64 0x21
String(l3)
"Hello, world!"