Menu

Floating Point Arithmetic with stirngs

2014-12-23
2018-07-20
  • Dimitris Katsaounis

    A first attempt to handle decimal numbers in GCBasic. They work well in PIC18F2550 but should be tested in other MCUs. I hope to help some friends out there

    Dim FirstFloat , SecondFloat , SysString , DecimalLength as String * 10
    Dim IntegerPart1 , IntegerPart2 as String * 5
    Dim DecimalPart1 , DecimalPart2 as String * 4
    Dim DotSing as String * 1
    Dim DecimalPart , IntegerPart as Word
    Dim Multi1 , Multi2, Multi3 as Long
    Dim SysStrDat as Byte

    'Add two strings as Floating numbers and return the result as string
    Function AddFloat (In FirstFloat(), In SecondFloat()) As String * 10 'Handle numbers up 65535.9999
    Call Normalize ( FirstFloat() , SecondFloat())
    DecimalPart=Val(DecimalPart1)
    DecimalPart=DecimalPart+Val(DecimalPart2)
    IntegerPart=Val(IntegerPart1)
    IntegerPart=IntegerPart+Val(IntegerPart2)
    DecimalLength=left(SysString , Len(DecimalPart1)+1)
    if DecimalPart> Val(DecimalLength)-1 then
    DecimalPart=DecimalPart % Val(DecimalLength)
    IntegerPart=[Word]IntegerPart+1
    End if
    AddFloat = Str(IntegerPart) + DotSing
    if DecimalPart<10 then SingLoc=3
    if DecimalPart>=10 and DecimalPart<=99 then SingLoc=2
    if DecimalPart>=100 and DecimalPart<=999 then SingLoc=1
    if DecimalPart>=1000 then SingLoc=0
    AddFloat=AddFloat+Right(SysString, SingLoc)
    AddFloat = AddFloat + Str(DecimalPart)
    for i=1 to 3
    if Right(AddFloat,1)="0" then
    AddFloat=Left(AddFloat, len(AddFloat)-1)
    end if
    next
    End Function

    'Multiply two strings as Floating numbers and return the result as string
    Function MultiFloat ( In FirstFloat(), In SecondFloat()) As String * 10
    DotSing="."
    SingLoc=Instr(FirstFloat,DotSing)
    IntegerPart1=Left(FirstFloat, SingLoc-1)
    SingLoc=Instr(SecondFloat,DotSing)
    IntegerPart2=Left(SecondFloat, SingLoc-1)
    SingLoc=Len(FirstFloat)-Instr(FirstFloat,DotSing)
    digit1=SingLoc
    DecimalPart1=Right(FirstFloat, SingLoc )
    SingLoc=Len(SecondFloat)-Instr(SecondFloat,DotSing)
    digit2=SingLoc
    DecimalPart2=Right(SecondFloat, SingLoc)
    FirstFloat=IntegerPart1+DecimalPart1
    SecondFloat=IntegerPart2+DecimalPart2
    Multi1 = Val32(FirstFloat)
    Multi2 = Val32(SecondFloat)
    Multi3=Multi1Multi2
    Multi1=1000000000
    SysCharCount=0
    Flag=0
    For i=1 to 10
    if Multi3>=Multi1 then
    SysStrData = Multi3 / Multi1
    Multi3 = Multi3- SysStrData
    Multi1
    SysCharCount += 1
    SysString(SysCharCount) = SysStrData + 48
    Flag=1
    else
    if Flag<>0 then
    SysStrData=0
    SysCharCount += 1
    SysString(SysCharCount) = SysStrData + 48
    end if
    end if
    Multi1=Multi1/10
    Next
    locate 0,0
    print SysString
    SysCharCount=len(SysString)
    Do While SysString(SysCharCount)="0"
    SysCharCount -=1
    SysString(0)=SysCharCount
    Loop
    SingLoc=digit1+digit2
    if SingLoc<SysCharCount then
    MultiFloat=Left(SysString, SysCharCount-SingLoc)
    MultiFloat=MultiFloat + "."
    else
    MultiFloat="0." + Mid("000000000",1,SingLoc-SysCharCount)
    end if
    MultiFloat=MultiFloat + Right(SysString, SingLoc)
    End Function

    'Converts a string to Long
    Function Val32(SysInString as String) as Long
    Val32=0
    SysCharCount = SysInString(0)
    For SysStringTemp = 1 to SysCharCount
    SysStrData = SysInString(SysStringTemp)
    Val32 = Val32 * 10 + SysStrData - 48
    Next
    end Function

    'Converts two numbers in one string as Floating number
    Function FloatToString (IntegerPart, DecimalPart) As String * 10
    FloatToString = Str(IntegerPart) + "."
    FloatToString = FloatToString + Str(DecimalPart)
    end Function

    'Extract the Integer part and the Decimal Part of Floating number in string
    Sub StringToFloat ( In FirstFloat , Out IntegerPart , Out DecimalPart)
    DotSing="."
    SingLoc=Instr(FirstFloat,DotSing)
    SecondFloat=Left(FirstFloat, SingLoc-1)
    IntegerPart = Val(SecondFloat)
    SingLoc=Len(FirstFloat)-Instr(FirstFloat,DotSing)
    SecondFloat=Right(FirstFloat, SingLoc )
    DecimalPart = Val(SecondFloat)
    End Sub

    Sub Normalize (FirstFloat() , SecondFloat())
    DotSing="."
    SysString="100000000"
    SingLoc=Instr(FirstFloat,DotSing)
    IntegerPart1=Left(FirstFloat, SingLoc-1)
    SingLoc=Instr(SecondFloat,DotSing)
    IntegerPart2=Left(SecondFloat, SingLoc-1)
    SingLoc=Len(FirstFloat)-Instr(FirstFloat,DotSing)
    DecimalPart1=Right(FirstFloat, SingLoc )
    SingLoc=Len(SecondFloat)-Instr(SecondFloat,DotSing)
    DecimalPart2=Right(SecondFloat, SingLoc)
    if len(DecimalPart1)<=3 then
    DecimalPart1=DecimalPart1+Right(SysString,4-len(DecimalPart1))
    end if
    if len(DecimalPart2)<=3 then
    DecimalPart2=DecimalPart2+Right(SysString,4-len(DecimalPart2))
    end if
    End sub

    My test program

    'Chip Settings
    #chip 18F2550, 8
    #config FOSC_INTOSC_HS, WDT=OFF, LVP=OFF, MCLRE=OFF, BOR=OFF

    'Includes
    #include "float.h"

    'Defines (Constants)
    #define LCD_NO_RW
    #define LCD_IO 4
    #define LCD_RS PORTB.5
    #define LCD_Enable PORTB.4
    #define LCD_DB4 PORTB.3
    #define LCD_DB5 PORTB.2
    #define LCD_DB6 PORTB.1
    #define LCD_DB7 PORTB.0

    'Variables
    Dim ab , ab1 , ab2, ab3 as string
    Dim x1 , x2 , x3 , x4 as Word

    'Handle numbers up 65535.9999

    x1=238
    x2=48 ' 238.48
    x3=29
    x4=6723 ' 29.6723
    ab1= FloatToString ( x1 , x2 )
    ab2= FloatToString ( x3 , x4)
    ab3 = AddFloat ( ab1 , ab2 )
    cls
    locate 1,0
    print ab3
    wait 5 s
    cls
    ab2 = AddFloat ( ab3 , "20.34" )
    locate 1,0
    print ab2
    locate 0,0
    print IntegerPart1
    locate 0, 5
    print DecimalPart1
    locate 0,11
    print IntegerPart2
    locate 1, 11
    print DecimalPart2
    wait 5 s
    cls
    locate 1,0
    print ab2
    Call StringToFloat ( ab2 , x1 , x2)
    locate 0,0
    print x1
    locate 0, 10
    print x2
    wait 5 s
    cls
    ab2 = MultiFloat ("234.06" , "0.073")
    locate 1, 0
    print ab2
    start:

    goto start

     
  • Anobium

    Anobium - 2014-12-24

    Nice piece of work!

    A lot of good work!!

    Well done.

     
  • Dimitris Katsaounis

    The SubFloat Function for Subtraction. Anobium please correct the << stirngs>> from the title because it "hits" my eye.

    'Subtract two strings as Floating numbers and return the result as string
    'FirstFloat is the minuend and SecondFloat is the subtrahend
    Function SubFloat (In FirstFloat(), In SecondFloat()) As String * 10
    SingFlag1=0
    SingFlag=0
    Carry=0
    Call Normalize ( FirstFloat , SecondFloat )
    Word1=Val(IntegerPart1)
    Word2=Val(IntegerPart2)
    if Word1<Word2 then="" SysString="FirstFloat" FirstFloat="SecondFloat" SecondFloat="SysString" SingFlag1="1" Call="" Normalize="" (="" FirstFloat="" ,="" SecondFloat="" )="" end="" if="" Word1="Val(DecimalPart1)" Word2="Val(DecimalPart2)" if="" Word1="">Word2 then
    DecimalPart=[Word]Word1-Word2
    End if
    if Word1=Word2 then
    DecimalPart=0
    end if
    if Word1<Word2 then="" DecimalPart="&lt;span">[Word]Word1+10000-Word2 Carry=1 end if Word1=Val(IntegerPart1) Word2=Val(IntegerPart2) if Word1>Word2 then
    IntegerPart=[Word]Word1-Word2-Carry
    SingFlag=0
    end if
    if Word1=Word2 then
    if Carry=0 then
    IntegerPart=0
    SingFlag=0
    else
    Word1=Val(DecimalPart1)
    Word2=Val(DecimalPart2)
    IntegerPart = 0
    DecimalPart=[Word]Word2-Word1
    SingFlag=1
    End if
    End if
    SubFloat=FloatToString (IntegerPart, DecimalPart)
    for i=1 to 3
    if Right(SubFloat,1)="0" then
    SubFloat=Left(SubFloat, len(SubFloat)-1)
    end if
    next
    if Right(SubFloat,1)="." then
    SysString=SubFloat+"0"
    SubFloat=SysString
    end if
    if SingFlag=1 or SingFlag1=1 then
    SysString="-"+SubFloat
    SubFloat=Left(SysString,10)
    End if
    End Function

     

    Last edit: Dimitris Katsaounis 2014-12-27
    • Mikam

      Mikam - 2018-07-20

      Hi Dimitris
      Very usefull. Have noticed this when multiplying.

      if MultiFloat ("0.3" , "0.3") answer 0.09
      if MultiFloat ("0.3" , "0.30") answer 0.009
      if MultiFloat ("0.30" , "0.30") answer 0.0009

      appears to add incorrect zero's

      Regards
      Mike

       
  • stan cartwright

    stan cartwright - 2018-04-12

    I want to draw attention to this and converting c code examples.
    No mention of this when I posted hard (decimal point) sums https://sourceforge.net/p/gcbasic/discussion/579125/thread/df78cd39/

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.