World: r3wp
[!REBOL3-OLD1]
older newer | first last |
Geomol 2-Jul-2009 [15901] | ah yes. :) You need larger numbers. Up to what number is the distance between numbers the same? 2.0? |
Ladislav 2-Jul-2009 [15902x3] | for sure, if the difference should be detectable, then you should try random 2 ** 1023 |
- in that case the chances are much higher, that you could detect any irregularities | |
do I understand correctly, that you prefer the variant including both endpoints? | |
Geomol 2-Jul-2009 [15905] | yes |
Ladislav 2-Jul-2009 [15906] | ...and your main reason is, that you know the endpoints exactly? |
Geomol 2-Jul-2009 [15907] | I'm in doubt about the distribution of numbers. Is this R2 function calculating ulps between two number ok? ulps: func [ value1 value2 /local d1 d2 ][ d: make struct! [v [decimal!]] none d1: make struct! [hi [integer!] lo [integer!]] none d2: make struct! [hi [integer!] lo [integer!]] none d/v: value1 change third d1 third d d/v: value2 change third d2 third d print [d1/hi d1/lo d2/hi d2/lo] print [d1/hi - d2/hi * (2 ** 32) + d1/lo - d2/lo] ] |
Ladislav 2-Jul-2009 [15908] | suggestion: R3 |
Geomol 2-Jul-2009 [15909] | The reason, I prefer your first version is: - I always know the endpoints exactly. - The mean is well defined. - The function is simpler and faster. |
Ladislav 2-Jul-2009 [15910x2] | REBOL [ Author: "Ladislav Mecir" Purpose: {Converts decimal to ordinal and back} ] make object! [ int-min: to integer! #{8000000000000000} set 'dec-as-int func [x [decimal!]] [ x: to integer! to binary! x either x < 0 [int-min - x] [x] ] set 'int-as-dec func [x [integer!]] [ if x < 0 [x: int-min - x] to decimal! to binary! x ] ] |
your "difference in ulps" is just the difference between the ordinal numbers | |
Geomol 2-Jul-2009 [15912x2] | So an R3 ulps could be: ulps: func [ lo [decimal!] hi [decimal!] ][ (to-integer to-binary hi) - to-integer to-binary lo ] |
>> ulps 0.0 0.1 == 4591870180066957722 >> ulps 0.1 0.2 == 4503599627370496 | |
Ladislav 2-Jul-2009 [15914] | (as-int hi) - (as-int lo) |
Geomol 2-Jul-2009 [15915] | It seems, numbers lie much closer around zero than around 0.1. |
Ladislav 2-Jul-2009 [15916] | sorry, (dec-as-int hi) - (dec-as-int lo) |
Geomol 2-Jul-2009 [15917x2] | >> (dec-as-int 0.1) - (dec-as-int 0.0) == 4591870180066957722 >> (dec-as-int 0.2) - (dec-as-int 0.1) == 4503599627370496 Same result. Now I'm confused! :-) |
If this is correct, then my suggestion to do random 1.0 many times will actually show the problem. | |
Ladislav 2-Jul-2009 [15919x2] | yes, you get different result only when trying (dec-as-int 0.0) - (dec-as-int -0.0) |
etc. | |
Geomol 2-Jul-2009 [15921x5] | The highest decimal is >> to-decimal #{7fef ffff ffff ffff} == 1.79769313486232e+308 There is the same number of ulps between 0.0 and 2.0 as between 1.0 and the highest decimal: >> ulps 0.0 2.0 == 4611686018427387904 >> ulps 1.0 to-decimal #{7fef ffff ffff ffff} == 4611686018427387903 I think, the space between number are different all the way from zero to the highest decimal, but I'm not sure. |
space between *numbers* are ... | |
Funnily enough, 1.5 is the middle value when talking ulps: >> ulps 0.0 1.5 == 4609434218613702656 >> ulps 1.5 hi == 4609434218613702655 | |
where hi is: hi: to-decimal #{7fef ffff ffff ffff} | |
This mean, there is as many different possible decimals between 0.0 and 1.5 as between 1.5 and the highest possible 64-bit decimal, when talking floating points in a computer using the 64-bit IEEE 754 standard. | |
Ladislav 2-Jul-2009 [15926x2] | how about this, do you think, that there is a problem with it too? two**62: to integer! 2 ** 62 two**9: to integer! 2 ** 9 two**53: to integer! 2 ** 53 r-uni: func [x [decimal!] /local d] [ d: random two**62 ; transform to 0..2**53-1 d: d // two**53 ; transform to 0.0 .. x (0.0 inclusive, x exclusive) d / two**53 * x ] |
a modification: two**62: to integer! 2 ** 62 two**53: to integer! 2 ** 53 two**53+1: two**53 + 1 r-uni: func [x [decimal!] /local d] [ d: random two**62 ; transform to 0..2**53 d: d // two**53+1 ; transform to 0.0 .. x (0.0 inclusive, x inclusive) d / two**53 * x ] | |
BrianH 2-Jul-2009 [15928] | When you two are done, could you look at CureCode ticket #1027 and R3's alpha 66 behavior and see if it is correct? I can't judge. |
Ladislav 2-Jul-2009 [15929x2] | LOL, that is what we are just discussing |
anyway, this is always a problem, when we try to generate numbers in an "exotic" interval, not in the usual [0.0 .. 1.0] | |
Geomol 2-Jul-2009 [15931] | I'll just grab some food, then I look at your r-uni. |
Ladislav 2-Jul-2009 [15932] | hmm, seems, that the former may still produce X when rounding? |
Gregg 2-Jul-2009 [15933] | In any case, this chat should be the basis for the docs that go with it. People aren't aware of how much thought goes into these things. |
Geomol 2-Jul-2009 [15934x2] | >> two**62 / two**53+1 == 512.0 So two**53+1 * 512 should equal two**62, but it doesn't: >> two**62 == 4611686018427387904 >> two**53+1 * 512 == 4611686018427388416 Why is that? |
(I wanted to check , if d // two**53+1 gave an even distribution, but there seem to be something wrong with calculations of large numbers.) | |
Ladislav 2-Jul-2009 [15936] | Why is that? - rounding |
Geomol 2-Jul-2009 [15937] | This should give an math overflow, I think: >> to integer! 2 ** 62 == 4611686018427387904 Like this does in R2: >> to integer! 2 ** 31 ** Math Error: Math or number overflow |
Ladislav 2-Jul-2009 [15938] | no, R3 uses 64-bit integers |
Geomol 2-Jul-2009 [15939x3] | no wait, it's 2 ** 63, that should give overflow. |
yeah | |
But!? :-) >> to integer! 2 ** 62 - 1 == 4611686018427387904 >> to integer! 2 ** 62 == 4611686018427387904 Isn't that a bug? | |
Ladislav 2-Jul-2009 [15942] | no, it is the precision limit of IEEE754 |
Geomol 2-Jul-2009 [15943] | I see. |
Ladislav 2-Jul-2009 [15944] | (I mean, it exceeds the precision limit) |
Geomol 2-Jul-2009 [15945x2] | Yes, I understand. |
After you do: d: d // two**53+1 Are we sure, the new d is even distributed? That every value, d can now take, is equal possible? | |
Ladislav 2-Jul-2009 [15947x2] | hmm, to make sure, I should use rejection |
as follows: rnd: func [ {random range with rejection, not using last bits} value [integer!] /local r s ] [ s: two-to-62 - (two-to-62 // value) until [ r: random two-to-62 r <= s ] s: s / value r - (r // s) / s + 1 ] | |
Geomol 2-Jul-2009 [15949] | If all possible values of d is equal possible, and d now can have values from 0 to two**53, then d / two**53 will return values from 0.0 to 1.0 both inclusive, and d / two**53 * x will return values from 0.0 to x both inclusive. Right? |
Ladislav 2-Jul-2009 [15950] | yes |
older newer | first last |