Shop OBEX P1 Docs P2 Docs Learn Events
Decimal point math in Spin — Parallax Forums

Decimal point math in Spin

garylakegarylake Posts: 41
edited 2011-03-12 08:26 in Propeller 1
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

Comments

  • John AbshierJohn Abshier Posts: 1,116
    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
  • Martin_HMartin_H Posts: 4,051
    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.
            long m_baseAngleRads
            long m_sholAngleRads
            long m_elboAngleRads
            long m_wrisAngleRads
            long m_wrisRotAngleRads
    
            ' 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
      SetShoulder(f32.FAdd(a1, a2))
    
      ' elbow angle
      SetElbow(f32.ACos(f32.FFloat((HUME_SQ + ULNA_SQ - s_w) / (2 * HUMERUS * ULNA))))
      elb_angle_rn := f32.FNeg(f32.FSub(STRAIGHT_ANGLE, m_elboAngleRads))
    
      ' wrist angle
      SetWristAngle(f32.FSub(f32.FSub(wristAngle, elb_angle_rn), m_sholAngleRads))
    
  • Heater.Heater. Posts: 21,230
    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.

  • evanhevanh Posts: 16,029
    edited 2022-03-29 07:56

    Floats have two major advantages:
    - Simplifies the writing and readability of source code.
    - Has a natural advantage in retaining full utilisation of the mantissa across multiplies and divides.

    Floats have two major disadvantages:
    - 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" :smile:

    I hate floats :lol:

    Craig

Sign In or Register to comment.