Converting from Float to Integer
3dogpottery
Posts: 78
I am crunching some numbers using the F32 floating point code. My results are in a range between plus and minus 127.0 (a 32 bit floating point number). I need to send this result to a Motor Mind B, so it has to be converted to a one byte integer between plus and minus 127 (the minus 127 must first be converted to 2's compliment). The F32 library of functions does not have anything to accomplish this. I cannot find anything in the Propeller Manual that addresses this either. Does anybody know whether this is even possible?
Comments
As long as the floating point number is within the range -127 to +127, you should be able to use the "FRound" method or "FTrucn" method and just send the lest significant byte to the Motor Mind B.
Here's one of many ways to do this.
By initially using a long to hold the value, you can accurately use comparisons with negative numbers.
Besides using a byte sized variable, you could also use the "byte" command to access a single byte within a long. I don't use this often enough to remember the syntax without looking it up.
Edit: I initially used the "FloatRound" instead of "FRound". They are not the same. "FloatRound" leaves the number encoded as a float.
if i => 0
send forward command
send i.byte[0] * 2 ' multiply by 2 since your max value is 127 and Motor Mind B max value is 255
else
send reverse command
send (i.byte[0] & $7F) * 2 ' & $7F to get rid of sign bit and rescale
John Abshier
I don't think your code would work as expected.
127 in binary is b0111_1111
-127 is b10000001
I'm using "b" instead of the percent sign so I can keep using the WYSIWYG editor.
I think your code would convert -127 to 2.
Spin does have an absolute value operator "||". Another option would be to multiple the number by negative one.
Edit: BTW, John is showing how to use a single byte in a long.
The method "FRound" will convert a float to an integer. You just stick the resulting number in a byte sized variable or use a single byte of the long (or word) in which it's stored.
byte positive integers aren't encoded differently than long positive integers.
[ code ]
VAR
long Along
byte Abyte
PUB
Along := 114.2
if (Along => 0)
Abyte := F32.FRound(F32.FMul( F32.FAbs(Along), 127.0))
else
Abyte := !F32.FRound(F32.FMul(F32.FAbs(Along), 127.0)) + 1
[ /code ]
I didn't realize that FRound returned an integer. I assumed that it rounded a float, and returned a float. But of course, if you round a float, you are dropping the fractional part of the number. Naturally, the result is an integer.
The "FloatRound" method does return a floating point number. It drops the fractional part of the number but keeps the number encoded as a float. There are two different "Round" methods in F32. One returns an integer and the other a floating point number.
BTW, you need to remove the spaces in your code tags. [ code ] should be [code]. You also need to remove the spaces in closing tag.
FRound can handle also negative numbers so I think you can replace this with: If you want to show the byte value in a terminal you need the sign extend operator to see the negative number:
term.dec(~Abyte)
Andy
Andy, I thought you need to start with a 16-bit number to use sign extend?
Am I missing something (as I often do)?
Yes you miss a tilde
One tilde for sign extend from a byte.
Two tildes for sign extend from a word
Andy
Wow, I did not know that. Thank you!