cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Check out the JMP® Marketplace featured Capability Explorer add-in
Choose Language Hide Translation Bar
vince_faller
Super User (Alumni)

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
ih
Super User (Alumni) ih
Super User (Alumni)

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...

View solution in original post

7 REPLIES 7
Craige_Hales
Super User

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
vince_faller
Super User (Alumni)

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
Craige_Hales
Super User

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
vince_faller
Super User (Alumni)

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()"} ),
				ReadFunction( "text" )
			);
		);
	, //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
Craige_Hales
Super User

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
vince_faller
Super User (Alumni)

Re: UUID generator

Ahh, I see.  Same reason why 

 

 

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

Sorry if this was actually two different questions.  

 

Vince Faller - Predictum
ih
Super User (Alumni) ih
Super User (Alumni)

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...