I wonder if there is a fast way to get the fractional value a value between 0.0 and 1.0

If for example the value is:
22.5

I would like to get the 0.5 value.

I wonder if there is a fast way to do so?
Posted on 2001-11-13 19:32:50 by dxantos
What do you mean? Clamping usually would give 1.0 for 22.5?
I don't understand - what is the transformation you'd like to occur over the range of possible input values? MMX is the fastest clamping I know of - using the saturation instructions.

This question is more of an algorithm question. IMHO ;)
Posted on 2001-11-13 20:08:43 by bitRAKE
I think he just wants to get the fractional part?
Posted on 2001-11-13 20:12:08 by f0dder
duh, I feel so stupid. ;)

dxantos, I assume your using FPU?
fld st
frndint
fsubp
But this produces all kinds of results dependant on the rounding mode!
Or:
fist DWORD PTR
fisub DWORD PTR
Same problem. Set rounding mode to truncate for desired results.
Posted on 2001-11-13 21:52:28 by bitRAKE
I edited the original post. I was using the incorrect term, clamping instead of fractional part.

I mean not using the FPU the real4 is defined this way:

``````
s eeeeeeee mmmmmmmmmmmmmmm

s = sign bit
e = exponent bits
m = mantisa bits
``````

And for example if you want to see is a value is negative, positive or zero, without using the FPU, you could do this:

``````
mov eax, [floatValue]
cmp eax, 0
``````

Since the bit31 is the sign bit on both float and integers, and 0 is the same in both float and integer. this trick works (but only for comparing with 0).

and you change it to and absolute value without passing to the FPU using this algo:

``````
mov eax, [floatValue]
and eax, 7FFFFFFFh ;The sign is the last bit, 0 = positive or zero.
mov [floatValue], eax
``````

You can even clamp a value to 0 if its negative with this one:
``````
mov edx, [floatVal]
mov eax, edx
sar eax, 31     ; This will put the sign bit on every bit
not eax           ; Flips the bits. will be 0 if negative, 0FFFFFFFFh otw
and edx, eax  ; Change value to zero if negative
mov [floatVal], eax
``````

So I wonder if there is a trick to get the fractional value of a float (real4).
Posted on 2001-11-14 08:48:14 by dxantos
There's a problem with the "integer compare to 0" method, though.
If you work a lot with the floating-point numbers, you risk building
up small errors, so you can have a value that *should* be 0, but
is rather 0.000000000001 (or whatever). Also, I believe floating
point values can be both +0 and -0 (which is pretty weird in when
thinking strictly mathematical... but floats are only approximations.)

Now, those statements are only based on stuff I've heard and such,
I haven't messed extremely much with floats, especially not where
precision was needed (I let my friend do that... I coded the fun stuff,
my friend had the chore of translating ugly mathematical expressions
into C code. Grin.)
Posted on 2001-11-14 08:56:23 by f0dder
f0dder: You are right, the value:

1 00000000 000000000000000000000000 b

is zero, altough it will pass as a negative.

Also if the exponent is 0 the number is a very tiny number, so near 0 that should be considered zero.

Thus:

``````
mov eax, [floatVal]
test eax, 07F800000 ; Test if exponent is zero.
jz @f
cmp eax, 0
@@:
``````

would be a more appropiate comparison, that dont care about negative zero. But this also mean a possible jump.

also if you want it to be precise to lets say 0.001
(well actually 1/(2^10) )

``````
mov edx, [floatVal]
mov eax, edx
and edx, 07F800000

.if edx < (127 - 10) * 800000h ; 1/(2^10)
;{
sub edx, edx ; Set flag to zero
;}
.else
;{
cmp eax, 0
;}
.endif

``````

for a 0.000001 precision (actually 1/(2^20) change the 10 to 20

I didn't take into account when the exponent is 255, this means the value is either a NAN, positive infinity or negative infinity. Fortunately this is rare, (unless you work with too big numbers). (To be honest I do not now what a number that is not a number "NAN" means). :)

bitRAKE : Thanks for your answer. Most of the time I leave the FPU on rounding mode, not truncate thus this will be slow for me to switch the FPU state for a single value.

Sorry to include this question in the game programming one.
I tough the algorithm section was to submit algorithms, and not asking for one. (I feel dumb).
Posted on 2001-11-14 09:56:55 by dxantos
For my uses the truncate mode offers more chances of optimization, and I can change most other alorithms to use that mode.
Posted on 2001-11-14 13:05:45 by bitRAKE