79545144

Date: 2025-03-30 20:53:30
Score: 1.5
Natty:
Report link

I tried to understand the algorithm involving bit operation, and end up with a doubt is this really useful ?
So first explaining how i understand the algorithm :

var bytes = new Byte[8];
rng.GetBytes(bytes);

This a simple "generate me 64 random bits", and it give a 8 bytes array.

var ul = BitConverter.ToUInt64(bytes, 0) / (1 << 11);

Well here is unnecessary divide operation as stated by the author himself in comment.
But I'll explain how i understand it :

  1. given or 64 bits randomly generated, convert them as an unsigned 64 bits integer. For example
    00011101_11100010_00000000_00001001_11101111_11100100_11110000_01011011

  2. perform a left shift bit operation on 1. Given we are working on 64 bits, it would result with 00000000_00000000_00000000_00000000_00000000_00000000_00001000_00000000 (52 0, a 1 and 11 0)

  3. Divide 1. by 2., which as a 2 64 bits numbers is a same as performing a right shift bit operation on 1. by same 11 bits shift.

  4. So in fact the result is 1. but with 11 0 bits first, and with the last extra 11 bits of 1. being discarded :
    00000000_00000011_10111100_01000000_00000001_00111101_11111100_10011110

Double d = ul / (Double)(1UL << 53);

This was the must perpetuating part, because it used the same math operation pattern, and so you might be tricked to think in bit operation again.
But it is not the case anymore because using a double cast here we are leaving the bit world to double one.

So here is a simple common divide operation on 2 doubles (the ulong result in 4. is implicitly converted to double at this step if I'm right).

And understanding the 1UL << 53 is also tricky here because you have to understand the left (and right) shift bit operation only consider the last 5 bits of the right operand on 32 bits world (int, uint ...), whereas it take the 6 last bits in 64 bits world (long, ulong, ... ). And as 53 in binary is 00110101 performing a left shift bit operation on 1 (implicitly a int32) would consider only the last 5 bits of 00110101 => 00010101 = 21. In order to correctly left shift 53 bits, you have to use 1UL instead to be in 64 bits world.
So here we are transforming 1UL in 00000000_00100000_00000000_00000000_00000000_00000000_00000000_00000000
(10 0, a 1 and 53 0)
Then come the double casting. But as you can see, 4. (1. right shifted 11 bits) result at most (if 1. is by chance only 1 bits) as :
00000000_00011111_11111111_11111111_11111111_11111111_11111111_11111111
Which is exactly (1UL << 53) - 1 !

So by dividing 4. result to 1UL << 53 we are simply dividing a random 53 bits binary number to its maximum (excluded) value !

---------------------------------
So here is my doubt after all this.
If this previous understanding is correct, then, why not simply create a random ulong integer like done here, and simply directly dividing it by its maximum value (if a potential issue is overflowing 64 bits, then consider generating a 63 bits integer and dividing it by System.Numerics.BigInteger.Pow(2, 64)-1 instead) ?

Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • Ends in question mark (2):
  • Filler text (0.5): ---------------------------------
  • Low reputation (0.5):
Posted by: TRex