r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[!REBOL3-OLD1]

Geomol
2-Jul-2009
[15881]
If you did e.g.

random 10.0


many many times, wouldn't you get a result, where 0.0 has a lot of 
hits, the first number higher than 0.0 will get close to zero hits, 
and then the number of hits will grow up to the number just below 
10.0, which will have almost as many hits as 0.0?
Ladislav
2-Jul-2009
[15882x2]
no, the hits are expected to be uniformly distributed, i.e. the same 
number of hits for 0.0 as for any interior point is expected
(if it does not work that way, then there is a bug)
Geomol
2-Jul-2009
[15884]
But the number lie much closer around zero than around 10.0.
Ladislav
2-Jul-2009
[15885]
aha, yes, the numbers aren't uniformly distributed; well, can you 
test it?
Geomol
2-Jul-2009
[15886]
So when you do the calculation going from a random integer and divide 
to get a decimal, you get a result between zero and 10.0. If the 
result is close to zero, there are many many numbers to give the 
result, while if the result is close to 10.0, there are much fewer 
possible numbers to give the result.
Ladislav
2-Jul-2009
[15887]
less numbers (lower density of numbers) = higher hit count per number
Geomol
2-Jul-2009
[15888x2]
yes
The result will look strange around zero. Many many counts for 0.0 
and very few counts for the following numbers.
Ladislav
2-Jul-2009
[15890]
but, that cannot influence the mean value
Geomol
2-Jul-2009
[15891x2]
yes, it does. I would say, of course it does. :)
You take a lot of hits for the max value and convert them to 0.0.
Ladislav
2-Jul-2009
[15893x2]
...it could influence the mean value only if the compiler used an 
"insensible" way of rounding
aha, more hits for the max...sorry, did not take that into account
Geomol
2-Jul-2009
[15895]
It could take a long long time to run an example showing this.
Ladislav
2-Jul-2009
[15896x2]
but, anyway, I am still pretty sure, that such a difference actually 
is undetectable
yes, you would have to run the test "almost forever" to see anything
Geomol
2-Jul-2009
[15898]
A test could be to run
random 1.0

many many times and save the results coming close to zero. Like my 
other test, checking if the result is within the first 1024 number 
close to zero. After running the test many times, a picture can be 
seen.
Ladislav
2-Jul-2009
[15899x2]
for random 1.0 you cannot find any irregularities, there aren't any
(the random numbers you may obtain are regularly spaced in that case)
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]