RE: 53-bit double
Hi Greg, All good. I think you described it fine. The question I had was more on what the big picture was. Why do it at all? And yes, there’d be a way to manipulate the bits to manually construct it, but in most languages, that’d be pretty ugly anyway. Regards, Greg Dr Greg Low 1300SQLSQL (1300 775 775) office | +61 419201410 mobile SQL Down Under | Web: https://sqldownunder.com<https://sqldownunder.com/> | About Greg: https://about.me/greg.low From: Greg Keogh Sent: Tuesday, 5 July 2022 8:58 AM To: Dr Greg Low Cc: ozDotNet Subject: Re: 53-bit double I might have missed it earlier Greg but was the actual problem that this helps with? I was intrigued by the underlying problem. I didn't express myself clearly originally. I was trying to convert a 64-bit random integer into a double and guarantee that all possible 2^53 floating values in the range 0 to 1 could result. Someone suggested that weird bit of earlier incomprehensible code, but it turns out a simple shift-and-multiply does that trick. There are lots of modern PRNGs that generate 64-bits, like the xoroshift** that is being used in the latest Random class. But how do you convert 64-bits "perfectly" into doubles? I finally confirmed a correct way. I'm still wondering if there is a way of manually constructing an IEEE 754 number from the raw bits, but it makes my head hurt. Cheers, GK
Re: 53-bit double
> > I might have missed it earlier Greg but was the actual problem that this > helps with? I was intrigued by the underlying problem. > I didn't express myself clearly originally. I was trying to convert a 64-bit random integer into a double and guarantee that all possible 2^53 floating values in the range 0 to 1 could result. Someone suggested that weird bit of earlier incomprehensible code, but it turns out a simple shift-and-multiply does that trick. There are lots of modern PRNGs that generate 64-bits, like the xoroshift** that is being used in the latest Random class. But how do you convert 64-bits "perfectly" into doubles? I finally confirmed a correct way. I'm still wondering if there is a way of manually constructing an IEEE 754 number from the raw bits, but it makes my head hurt. Cheers, *GK*
RE: 53-bit double
I might have missed it earlier Greg but was the actual problem that this helps with? I was intrigued by the underlying problem. Regards, Greg Dr Greg Low 1300SQLSQL (1300 775 775) office | +61 419201410 mobile SQL Down Under | Web: https://sqldownunder.com<https://sqldownunder.com/> | About Greg: https://about.me/greg.low From: Greg Keogh via ozdotnet Sent: Tuesday, 5 July 2022 8:37 AM To: ozDotNet Cc: Greg Keogh Subject: Re: 53-bit double uint u1 = [32 random bits]; uint u2 = [32 random bits]; uint a = u1 >> 5, b = u2 >> 6; return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); Can anyone explain this magic? Is this correct? This bit trick is no longer important to decode. I was trying to figure out how to convert a UInt64 of random bits into a normalised double in the range [0,1) in such a way that all 2^53 possible floating values could be produced. Some web sites suggested simply doing this: uint u = [64 random bits] double d = (u >> 11) * 1.11022302462515654e-16 // * 2-53 I was suspicious that subtle rounding problems might produce a defective output range, but a quick experiment in LINQPad that fed limit values into the calculation demonstrated that a complete set of significand bit patterns was generated at the limits. This supplies good evidence that the above shift-and-multiply converts 53 of the 64 random bits into a complete possible double range. Greg K
Re: 53-bit double
> > uint u1 = *[32 random bits]*; > uint u2 = *[32 random bits]*; > uint a = u1 >> 5, b = u2 >> 6; > return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); > > Can anyone explain this magic? Is this correct? > This bit trick is no longer important to decode. I was trying to figure out how to convert a UInt64 of random bits into a normalised double in the range [0,1) in such a way that all 2^53 possible floating values could be produced. Some web sites suggested simply doing this: uint u = *[64 random bits]* double d = (u >> 11) * 1.11022302462515654e-16 // * 2-53 I was suspicious that subtle rounding problems might produce a defective output range, but a quick experiment in LINQPad that fed limit values into the calculation demonstrated that a complete set of significand bit patterns was generated at the limits. This supplies good evidence that the above shift-and-multiply converts 53 of the 64 random bits into a complete possible double range. *Greg K*