Decimal point math in Spin — Parallax Forums

# Decimal point math in Spin

edited 2011-03-12 08:26
Simple question and I hope a simple answer.
In Spin I would like to use decimal point numbers for division.
Like 1000/1.5
or 1000/0.3

• edited 2011-03-12 07:33
Threre are floating point objects in the library. Plus there is the F32 object in the Object exchange. The Propeller Tool will do floating point math for constants.

John Abshier
• edited 2011-03-12 07:35
In Spin code the math operators are integer operations. To do floating point math you need to use a library object from OBEX (F32 by Jonathan "lonesock" Dummer is a good choice). You'll need to make function calls to perform operations instead of using the built in operations. In addition, you'll need to take care when mixing integer a floating point via explicit type conversions via function calls.

Here's some code I've been worrking on:
```CON
_clkmode       = xtal1 + pll16x
_xinfreq        = 5_000_000

' Angular values for common angles
RIGHT_ANGLE     = pi / 2.0
STRAIGHT_ANGLE  = pi
FULL_ROTATION   = 2.0 * pi

' Arm dimensions in mm
BASE_HGT        = 67    ' base hight 2.65"
HUMERUS         = 146   ' shoulder-to-elbow "bone" 5.25"
ULNA            = 187   ' elbow-to-wrist "bone" 7.375"
GRIPPER         = 100   ' gripper (incl. wrist rotate mechanism) length 3.94"

' pre-calculations for right triangle trig.
HUME_SQ = HUMERUS * HUMERUS
ULNA_SQ = ULNA * ULNA

OBJ
f32     : "F32"
fs      : "FloatString"

VAR
' Coordinates in arm polar space.

' Coordinate of gripper tip in cartesian space.
long m_x
long m_y
long m_z

PUB main
' start up the floating point objects and my serial link
f32.start

PUB SetPosition(x, y, z, wristAngle) | grip_off_y, grip_off_z, wrist_y, wrist_z, s_w, s_w_sqrt, a1, a2, elb_angle_rn
{{
SetPosition : Arm positioning routine utilizing inverse kinematics.  Since the arm is
resting on a surface Z can only be positive.  Servo movement contraints prevent y
from being negative, But X can be a signed value.
Parameters:
x   the side to side displacement.
y   the distance out from the base center.
z   the height above the table
wristAngle    wrist angle of the gripper in radians.
}}
' Save the cartesian space coordinates.
m_x := x
m_y := y
m_z := z

' Convert x and y to float and compute a polar angle to position the base.
SetBase(f32.ATan2(f32.FFloat(x), f32.FFloat(y)))

' Compute the vector magnitude and hold in the y coordinate.
y := ^^((x * x) + (y * y))

' Convert gripper length to float and use for Gripper offsets calculated
' based on grip angle and convert back to integer with rounding.
grip_off_y := f32.FFloat(GRIPPER)
grip_off_z := f32.FRound(f32.FMul(f32.Sin(wristAngle), grip_off_y))
grip_off_y := f32.FRound(f32.FMul(f32.Cos(wristAngle), grip_off_y))

' Wrist position
wrist_z := (z - grip_off_z) - BASE_HGT
wrist_y := y - grip_off_y

' Shoulder to wrist distance is a hypotenuse ( AKA sw )
s_w := (wrist_z * wrist_z) + (wrist_y * wrist_y)
s_w_sqrt := ^^ s_w

' s_w angle to ground
a1 := f32.ATan2(f32.FFloat(wrist_z), f32.FFloat(wrist_y))

' s_w angle to humerus
a2 := f32.ACos(f32.FFloat(((HUME_SQ - ULNA_SQ) + s_w) / (2 * HUMERUS * s_w_sqrt)))

' shoulder angle

' elbow angle
SetElbow(f32.ACos(f32.FFloat((HUME_SQ + ULNA_SQ - s_w) / (2 * HUMERUS * ULNA))))

' wrist angle
```
• edited 2011-03-12 08:26
Garylake,

Notice that 1000/1.5 is the same as 10000/15
So you see that if you scale up your numbers by 10 or 100 you can easily handle one or two decimal places respectively.
This called fixed point arithmetic and is often sufficient.
Also be carefull of overflow when you do this.
• @anybody

Does anyone have a copy of this:F32 - Concise floating point code for the Propeller.
Github gave me a 404 on this.
Thanks

• @"Heater." said:
Notice that 1000/1.5 is the same as 10000/15
So you see that if you scale up your numbers by 10 or 100 you can easily handle one or two decimal places respectively.
This called fixed point arithmetic and is often sufficient.

`*` and `**` easily allow 32bit fixed point math. That's good enough even for some fun some wouldn't expect.

• @"Heater." said:
This called fixed point arithmetic and is often sufficient.

And remember, as Heater's boss used to say "if you think you need floats, you're not doing it right." (Or something like that.)

Heater used to bring this up when someone asked about floating point math and I often remind myself of this advice. I actively avoid using floats in my Propeller projects.
Here's one example of why.
What's next highest number after one billion?
With integer math the answer is 1,000,000,001.
With 32-bit floating point math, the answer is 1,000,000,064.

There may be times when floats are a better option than using integers, but most (almost all) the times in the past when I initially thought floats were the better option, it turned out I was wrong and Heater's boss was right. You're almost always better off using integer math rather than floating point math. It turns out you don't even need floats for trig equations.

I haven't been able to eliminate floats completely from my programs but I always feel like I've failed a bit as a programmer when I need to use them.

• edited 2022-03-29 07:56

- Simplifies the writing and readability of source code.
- Has a natural advantage in retaining full utilisation of the mantissa across multiplies and divides.

- Sacrifices mantissa size to have the exponent.
- Slower and has overheads when not in hardware.

I like to use both Integers and Floats - Even with a fast FPU at hand. Integers serve as precise adders that can be mapped to real world I/O without any fuzziness, so often that's exactly how I use them. Floats are better when doing the intermediate transforming maths.

• Simplifies the writing and readability of source code.

Except in Spin, here all floating-point computations have to be done via function calls, rather than infix expressions.

-Phil

• @""Duane Degn"

"If you can't solve the problem with integers, you don't understand the problem" I hate floats Craig