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

World: r3wp

[Rebol School] Rebol School

kib2
23-Feb-2009
[2341]
Thanks Geomol. I think I have to study game programming before!
kib2
24-Feb-2009
[2342x2]
How could I generate a random number (a real number) between 2 given 
values, ie between -pi and pi ?
random pi gives me an integer
Henrik
24-Feb-2009
[2344]
interesting
Geomol
24-Feb-2009
[2345]
I can think of a way to do it, but it isn't easy. I have a feeling, 
REBOL has a problem with random decimals.
Henrik
24-Feb-2009
[2346]
I've posted this issue on rebdev. R3 rounds decimals as well.
Geomol
24-Feb-2009
[2347x6]
You can build a hex value from an integer with TO-HEX.
And you can put that hex value into a decimal using struct!
So something like:

>> d: make struct! [v [float]] none
>> i: to integer! (random 2 ** 32) - (2 ** 31) - 1
== -198913422
>> h: to-hex i
== #F424D272
>> change third d h
>> d/v
== 11532.55078125
To get the result between some values, you have to use a factor somewhere.
hm, I'm not sure, this is right. The length of third d is 8. It should 
be 4, I guess.
Yeah, the change line should read:

change third d debase/base h 16

I said, it wasn't easy. ;-P
I'm wondering, if this has come up before? I didn't find a random 
decimal function in the library (rebol.org). Some of the math guys 
here may have a better way?
Henrik
24-Feb-2009
[2353]
how about randoming a big integer and divide by that integer and 
multiply with your desired max-value?
Geomol
24-Feb-2009
[2354]
Yes, that's an easy way, but I'm afraid rounding will lead to the 
result not being very random (or a limit in possible outcome). It 
has to be checked at least.
Anton
24-Feb-2009
[2355]
Rebol decimal! is 8 bytes and integer! is only 4 bytes. So you would 
need to make a struct of 2 integer!, then swap its contents with 
a struct of 1 decimal!
Geomol
24-Feb-2009
[2356]
I used float up there, which is 32 bit afaik. What do I write to 
make a 64 bit decimal struct?
Anton
24-Feb-2009
[2357x2]
You wrote float, but you didn't get one :)
You can write make struct! [v [decimal!]] none
Geomol
24-Feb-2009
[2359]
ah :D
kib2
24-Feb-2009
[2360]
Sorry guys, I was away for an hour. Henrik : that's the way I was 
thinking of it, but it seems weird.
Geomol
24-Feb-2009
[2361x3]
I'm wondering, why I got that float into my head.
Anton, are you sure, I don't get a 4 byte float?

>> d: make struct! [v [float]] none
>> d/v
>> type? d/v
== decimal!
>> length? third d
== 4

The length of a decimal is 8.
missed a line:

>> d/v
== 0.0
Anton
24-Feb-2009
[2364x6]
... no longer sure ...! :-)
My error, sorry.
http://www.rebol.com/docs/library.html#section-4.2
d: make struct! [v [decimal!]] none
i: make struct! [v1 [integer!] v2 [integer!]] none

i/v1: to integer! (random 2 ** 32) - (2 ** 31) - 1
i/v2: to integer! (random 2 ** 32) - (2 ** 31) - 1

change third d third i
The random decimal is d/v
Now divide by max-decimal (whatever that is) and multiply by desired 
range (eg. pi).
Geomol
24-Feb-2009
[2370x2]
:-) I follow you, when you say, you're no longer sure. This is a 
little used corner of REBOL (for me at least).


I think, we have a problem still. random 2 ** 32 seem to never give 
results above 2 ** 31.
Never returns:

>> until [a: random 2 ** 32 a > (2 ** 31)]
Anton
24-Feb-2009
[2372]
That would be a problem, yes.
Geomol
24-Feb-2009
[2373]
And since we don't have a 16 bit datatype (or maybe we do with a 
string or other series somehow!?), we have to make 8 times random 
256 (and subtract 1).
Anton
24-Feb-2009
[2374]
We can substitute the struct of 2 integer!s with a struct of 8 char.
Maybe this is useful:
>> random 255.255.255.255.255.255.255.255
== 168.97.60.251.15.20.205.31
Geomol
24-Feb-2009
[2375]
Kib asked a simple question about random and decimals. It seems to 
be a bit of a hazzle to get what we want, and this should be pointed 
out to Carl for R3, I think.
Anton
24-Feb-2009
[2376]
but can't put tuple! in struct directly...
kib2
24-Feb-2009
[2377]
Sometimes I wonder why such simple things are not implmented natively 
in REBOL.
Geomol
24-Feb-2009
[2378]
Kib, I think, the answer is, that REBOL do a lot and then some more, 
but there are a few holes.
kib2
24-Feb-2009
[2379]
Yes, this one and repeating a string are essential to me. I may find 
other cases too :)
Anton
24-Feb-2009
[2380x3]
random also doesn't return 0.
(ah.. that's why you subtracted 1, never mind.)
The other thing I was thinking we might need to watch out for is 
the production of invalid decimals. Maybe some mantissa combinations 
are not valid?
Geomol
24-Feb-2009
[2383x2]
:-)

Kib, feel free to ask questions about all this. It may easily get 
blurred, when we talk like this. And it shows you, that we're often 
in doubt, because REBOL is so deep. (I hope, it's ok, we do this 
in the Rebol School group.)
Right, Anton, I forgot about that.
Anton
24-Feb-2009
[2385]
Let's switch to the Math group.
Geomol
24-Feb-2009
[2386x3]
Maybe the invalid decimal can be handled with some: if error? try 
[...]
Kib, there might be a good explanation, why there's no random decimal 
in REBOL. See:

http://stackoverflow.com/questions/439115/random-decimal-in-python
It's not a trivial problem.
You asked how to make a random number between e.g. pi and -pi. There 
are a number of ULPs (Unit in the Last Place) between those two numbers. 
For 64 bit decimals, it's a large number. The possible decimals in 
computer arithmetic lie closer together around zero than for large 
numbers. If you had a routine, that would give you any possible 64 
bit decimal number between pi and -pi with equal probability, then 
you would get a lot more numbers close to zero than close to either 
pi or -pi. The distribution wouldn't be flat (as you would expect).


It's much better to choose, how many different values between pi 
and -pi, you need, and then make a random integer of that number, 
and do some calc to get the result between pi and -pi.

I hope, it makes sense.
kib2
24-Feb-2009
[2389x2]
I came with this, what do you think of it ? (highly criticable) :

random-dec: func[i n /local ent dec] [
    "generates a decimal : i digits before, n digits after"
    ent: to-integer random i
    dec: to-integer random n
    return to-decimal rejoin [ent "." dec]
]

print random-dec 9999 999999 ; 4 digits before 6 after
Or even :

random-dec: func[i n /fromdigits /local ent dec] [
    "i digits before, n after"
    
    if fromdigits [
        "i: number of digits before, n: number of digits after"
        i: 10 ** i - 1
        n: 10 ** n - 1
    ]
    
    ent: to-integer random i
    dec: to-integer random n
    return to-decimal rejoin [ent "." dec]
]

print random-dec 999 99999 ; 3 digits before, 5 after
print random-dec/fromdigits 4 6 ; 4 digits before, 6 after