BookmarkSubscribe
Choose Language Hide Translation Bar

UUID generator

I'm trying to make a standard guid, but hex() is giving me a weird value. I assume it's because of the encoding hex() uses.

Can anyone give me some clarity on the below script? Or if someone even just has a UUID function that would be even better.

Names default to here(1);
full_h = "123e4567-e89b-12d3-a456-426655440000";
h = substitute(h, "-", "");
n = hex to number(h);
h_again = hex(n);
n_again = hex to number(h);
show(h == h_again, n == n_again);

Thanks

Vince Faller - Predictum
1 ACCEPTED SOLUTION

Accepted Solutions

Re: UUID generator

Here is a method to create a UUID:

newuuid = function({},
//following procedure here: https://www.cryptosys.net/pki/uuid-rfc4122.html
strout = "";
//guid made from 16 hex bytes
for(i=1, i<=16, i++,
thisint = random integer(256) - 1;
thisbyte = right(hex(thisint,"integer"),2);
if( i == 7, //the four most significant bits of the of the 7th byte are 0100
thisbyte = char(4) || right(thisbyte,1),
i == 9, //the two most significant bits of the 9th byte are 01
//decimal to binary
bin = "";
value = thisint;
While(value,
bin = Char(Modulo(Num(value), 2)) || bin;
value = Floor(value / 2);
);
//fix digits
bin = right(bin,8,"0");
bin = "10" || right(bin, 6);
//back to decimal
dec = 0;
While(length(bin) > 0,
dec = dec + (num(left(bin, 1))*2)^(num(length(bin))-1);
bin = right(bin, length(bin) - 1);
);
//to hex
thisbyte = right( hex( dec, "integer" ), 2 );
);
strout = strout || thisbyte;
);
//format output
substr(strout,1,8) ||
"-" || substr(strout,9,4) ||
"-" || substr(strout,13,4)||
"-" || substr(strout,17,4) ||
"-" || substr(strout,21,12);
);

newuuid();

Disclaimer: I believe I blindly followed this link and I didn't do extensive testing...

7 REPLIES 7
Highlighted

Re: UUID generator

It looks like you already have a guid, and are trying to pack it into another representation.

guid = "123e4567-e89b-12d3-a456-426655440000";
guid = substitute(guid,"-","");
blob=hextoblob(guid);
show(hex(blob)); //  "123E4567E89B12D3A456426655440000";

it is not possible to keep the 16 bytes in two 8-byte doubles without hitting missing value issues; the 16 byte blob (or 32 character hex representation) seems reasonable. I don't think JMP exposes a function to create guids; the OS typically forms them from your machine's MAC address, time-of-day, and maybe some other information that should make them nearly unique.

HexToNumber in JSL has a second argument that specifies what sort of encoding the hex represents. I think it may make a special case for exactly 16 hex characters being a double and less than or equal to 8 being a 4-byte integer.

You might find it helpful to load the blob (above) into a matrix of 1-byte unsigned integers if you are trying to disassemble the guid into its components. (blobToMatrix function). You might roll your own guid too, https://superuser.com/questions/892700/is-there-a-way-to-get-only-the-ethernet-mac-address-via-comma...

https://en.wikipedia.org/wiki/Universally_unique_identifier

Craige

Re: UUID generator

I wasn't trying to pack it into a different representation.  I was actually just trying to test with a random 128 bit number and noticing that two VERY different sized hex strings were coming out to be the same number and was trying to figure out how.

Or maybe more succinctly.  Why is this true?

hextonumber("47B23E4567E89B13") == hextonumber("123e4567e89b12d3a456426655440000")
Vince Faller - Predictum

Re: UUID generator

OK, if you give it exacly 16 hex digits, it tries to make an IEEE double. Otherwise it builds an integer, probably in the 53-bit part of a double, and if there are more than about 53/4 (13?) hex digits it both loses precision and displays as if it were a double. None of that is useful for what you are trying to do.

Craige

Re: UUID generator

haha.  I'll have to look that stuff up.  Thanks for the help.

I could run under the assumption the user has powershell and just get it through that.  I'd have to write a mac equivalent though.

Names default to here(1);
create_uuid = function({},
{DEFAULT LOCAL},
txt = "";
if(hostis("Windows"),
logtxt = logcapture(
txt = Run Program(executable("Powershell.exe"),
Options( {"[guid]::NewGuid()"} ),
);
);
, //else
throw("I don't think Apple has powershell");
);

if(txt != "",
uuid = regex(txt, "[\w\d]{8}-[\w\d]{4}-[\w\d]{4}-[\w\d]{4}-[\w\d]{12}");
return(uuid);
, // elif
Contains(logtxt, "RunProgram Error"),
throw(trim(logtxt));
, //else
throw("Couldn't find UUID");
);
);
create_uuid();

Vince Faller - Predictum

Re: UUID generator

And the answer to the question:

2.4249434048109e+37 is a double precision number, represented in hex as the left-hand-side of your question. The huge hex value on the right side is an integer that is approximately the same value. It would need a lot more than 53 or 64 bits to accurately represent it.

Maybe the hex to number function should warn about the loss of precision. @EvanMcCorkle

Craige

Re: UUID generator

Ahh, I see.  Same reason why

hextonumber("123e4567e89b12d3a456426655440001") == hextonumber("123e4567e89b12d3a456426655440000")

Sorry if this was actually two different questions.

Vince Faller - Predictum

Re: UUID generator

Here is a method to create a UUID:

newuuid = function({},
//following procedure here: https://www.cryptosys.net/pki/uuid-rfc4122.html
strout = "";
//guid made from 16 hex bytes
for(i=1, i<=16, i++,
thisint = random integer(256) - 1;
thisbyte = right(hex(thisint,"integer"),2);
if( i == 7, //the four most significant bits of the of the 7th byte are 0100
thisbyte = char(4) || right(thisbyte,1),
i == 9, //the two most significant bits of the 9th byte are 01
//decimal to binary
bin = "";
value = thisint;
While(value,
bin = Char(Modulo(Num(value), 2)) || bin;
value = Floor(value / 2);
);
//fix digits
bin = right(bin,8,"0");
bin = "10" || right(bin, 6);
//back to decimal
dec = 0;
While(length(bin) > 0,
dec = dec + (num(left(bin, 1))*2)^(num(length(bin))-1);
bin = right(bin, length(bin) - 1);
);
//to hex
thisbyte = right( hex( dec, "integer" ), 2 );
);
strout = strout || thisbyte;
);
//format output
substr(strout,1,8) ||
"-" || substr(strout,9,4) ||
"-" || substr(strout,13,4)||
"-" || substr(strout,17,4) ||
"-" || substr(strout,21,12);
);

newuuid();

Disclaimer: I believe I blindly followed this link and I didn't do extensive testing...