Dumb Spin question
David Betz
Posts: 14,516
Can the || (absolute value) operator ever return a negative number? I'm thinking of the case where the input value is the largest negative number $80000000. If you negate that you get the same value back. Will the || operator do that and return a negative value for that case?
Edit: Maybe it would be good if I describe what I'm trying to do. I want to generate a random number between 0 and n-1 and am trying to do it like this:
Edit: Maybe it would be good if I describe what I'm trying to do. I want to generate a random number between 0 and n-1 and am trying to do it like this:
x := ||?seed // nHowever, I'm afraid that if ?seed returns $80000000 then I'll get a negative result.
Comments
hope this helps
It's not a minus zero, it's -2147483648. There's no such thing as minus zero in two's complement arithmetic. It isn't adjacent to any numbers remotely near zero. It could be either -2147483648 or 2147483648, since it's adjacent to both -2147483647 and 2147483647, but the standard interpretation is that it is negative because numbers with their top bit set are negative.
I ran the following C program on my computer with no optimization, and it printed out -2147483648 twice:
-Phil
Its 2's compl_e_ment, not compl_i_ment and $80000000 _is_ a negative value and is completely meaningful,
but happens to have no representation of its absolute value in 32 bits.
https://en.wikipedia.org/wiki/Two%27s_complement
I would have thought that the opposite would be true, that the & operation would require fewer bytecodes. Can you explain why?
Thanks,
Walter
To be fair, result is different given the same seed. For applications where a random value is desired, this is okay. To have the same result using these techniques the shifting variant would have to be changed to:
...which now takes 992 ticks.
For grins I opened BST to look at the compiled output:
Seems like the speed difference from the original comparison is due to an extra hub read.
Anyway, I agree with JonnyMac that "x >> 1" is faster than "x & $7FFF_FFFF" because the constant 1 is only one byte of PNUT ($36: push 1) while $7FFF_FFFF is two ($37 $3E: push constant mask, Y = $3E). I'll bet the >> and & operators themselves take exactly the same amount of cycles to run.
Try this then just for grins:
I get the following as a a result:
80000001
-2147483647
7FFFFFFF
2147483647
80000000
-0
80000000
-0
The actual amount of time varies depending on what n is, but typically:
||(seed // n) executes in ~1408
seed >> 1 // n executes in ~1568
seed & $7FFF_FFFF // n executes in ~1616