World: r3wp
[Rebol School] Rebol School
older newer | first last |
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 | |
[unknown: 5] 24-Feb-2009 [2391] | You shouldn't need the return statement. The last value will be returned unless a return is found elsewhere. |
older newer | first last |