Announcement

Collapse
No announcement yet.

Convert string number to negative number

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Convert string number to negative number

    Hi everybody,

    This may sound like a strange request but I need to know how I convert
    a number that is represented as string into a NEGATIVE value with the least
    amount of CPU cycles. The result should be a numeric variable.
    Code:
    Dim extA as Ext
    Dim A as String
    A = "5"
    A = "-" & A
    extA = Val(A)
    Eventually there is an operation on the result and that result is stored as
    a string.

    Or are there other tricks.

    Steven
    So here we are, this is the end.
    But all that dies, is born again.
    - From The Ashes (In This Moment)

  • #2
    Just starting with what you wrote, this will save a string concatenation:
    Code:
    Dim extA as Ext
    Dim A as String
    A = "5"
    extA = -Val(A)
    But I'm not sure if I understood correctly...

    Bye!
    -- The universe tends toward maximum irony. Don't push it.

    File Extension Seeker - Metasearch engine for file extensions / file types
    Online TrID file identifier | TrIDLib - Identify thousands of file formats

    Comment


    • #3
      There is no shortcut (that I know of) to do run-time calculations from a string. Search the forum for "math parser" or "expression evaluator"
      kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

      Comment


      • #4
        Thanks Marco, Kev,

        I was actually looking for something more low level (even ASM) e.g. by manipulating the bit order itself but I guess that the process involved
        will be quite complex especially when dealing with floating point numbers
        that are first represented as a string and then should be made negative.
        So here we are, this is the end.
        But all that dies, is born again.
        - From The Ashes (In This Moment)

        Comment


        • #5
          Do something like this, except instead of hex digits, use decimal digits and manage your own carries.
          Byte to HEX character pair and vice-versa conversions

          Frankly, to suggest that -1& * VAL(string) is not fast enough is an insult to the compiler developers. They have been doing this for 20+ years and maybe, just maybe have learned a few things about doing it well and doing it quickly.

          Of course, VAL() does support various forms of numbers (explicit decimal points, binary, octal and hex representations) as well as scientific notation (E or D in string), so if you can restrict the input to known decimal digits plus zero or one explicit decimal points, the substitution table thing ought to be worth a shot.
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            However, once you have an EXT (or single or double for that matter) you can negate it by simply setting the sign bit (use OR or BIT SET ) .

            That is, once you have an EXT.
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              OR (guess because code not shown, application not described)....

              If you want to do this fast, it suggests you have "many".

              Because it's a number, it suggests you want to do some arithmetic on it.

              Maybe you can do the negation when you do the arithmetic - once per number, instead of negating each potential operand individually.
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                VAL doesn't support this (which I believe is what Steven meant):

                Code:
                 
                calc = VAL("(2 + 2) * 5")
                You need a math parser or roll-your-own.
                kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

                Comment


                • #9
                  Divide by minus one.

                  temp = val(string) / -1
                  There are no atheists in a fox hole or the morning of a math test.
                  If my flag offends you, I'll help you pack.

                  Comment


                  • #10
                    QuickPak Pro has/had QPValI and QPValL for siimilar things,but never for EXT.
                    There might be a math library available somewhere.
                    I requested a stripped down VAL, but the request was rejected.

                    This is just playing around to see the bytes.
                    Code:
                    #COMPILE EXE
                    #DIM ALL
                    UNION EXT_UNION
                      s AS STRING * 10
                      b(1 TO 10) AS BYTE
                      e AS EXT
                    END UNION
                    FUNCTION PBMAIN () AS LONG
                      DIM e AS EXT
                      DIM s AS STRING
                      DIM u AS EXT_UNION
                      DIM x AS LONG
                      u.e = -5
                      FOR x = 1 TO 10: PRINT u.b(x);: NEXT:PRINT
                      WAITKEY$
                    END FUNCTION
                    Hi Steven
                    Last edited by Mike Doty; 6 Feb 2009, 10:47 AM.

                    Comment


                    • #11
                      Hi Michael, Mel,

                      I like both your solutions. The obvious is to /-1 but I'll check out the OR and BIT SET alternatives. Thanks !
                      So here we are, this is the end.
                      But all that dies, is born again.
                      - From The Ashes (In This Moment)

                      Comment


                      • #12
                        Can your strings be limited to a range smaller than EXT?
                        Are they always floating point?

                        String to long.
                        http://www.powerbasic.com/support/pb...ad.php?t=25163
                        Last edited by Mike Doty; 6 Feb 2009, 11:11 AM.

                        Comment


                        • #13
                          *-1 is faster than /-1
                          Old QB45 Programmer

                          Comment


                          • #14
                            Not the fastest and has no error checking, assumes the string is +ve and has only characters 0 to 9 and decimal point. It may get you started

                            Code:
                            PBCC5 program
                            FUNCTION PBMAIN () AS LONG
                            #REGISTER NONE
                            
                            LOCAL MyNumber AS ASCIIZ *100
                            
                            MyNumber="12345.012345645675"
                            ten!=10
                            tenth##=1/10##
                            temp&=0
                            answer##=0
                            
                            
                            DIM extA AS EXT
                            DIM A AS STRING
                            A = MyNumber
                            
                            TIX t&&
                            'A = "-" & A
                            extA = -VAL(A)
                            
                            TIX END t&&
                            PRINT "time="t&&
                            PRINT extA
                            
                            
                            
                            TIX t&&
                            
                            !lea eax,MyNumber       'get address of string, it's zero terminated
                            !fld ten!               'some useful values for the FPU, 10
                            !fldz                   ' zero (the initial value for the answer)
                            
                            'do the integer part
                            lp:
                            !movzx ecx,byte ptr [eax]   'get current byte
                            !inc eax                    'point to next byte
                            !cmp cl,0                   'is current byte zero? (end of string)
                            !je skip                    'yes, exit
                            !cmp cl,"."                 'is it a decimal point?
                            !je fraction                'yes, do the fraction part
                            
                            
                            !sub ecx,"0"                'no, convert ascii character to binary
                            !mov temp&,ecx              'transfer the byte to the FPU
                            !fmul st(0),st(1)           'multiply answer so far by 10
                            !fild temp&                 'get digit
                            !faddp st(1),st(0)          'add it in to the answer
                            
                            !jmp short lp               'go back for next character
                            
                            fraction:
                            !fldz                       'start the fractional part off at zero
                            !fld tenth##                'some useful values for the FPU, 1/10 (the scale for the fractional multiplier)
                            !fld1                       ' 1  (the fractional mutiplier)
                            
                            
                            lp2:
                            !movzx ecx,byte ptr [eax]   'get current byte
                            !inc eax                    'point to next byte
                            !cmp cl,0                   'is current byte zero? (end of string)
                            !je skip2                    'yes, exit
                            
                            !sub ecx,"0"                'no, convert ascii character to binary
                            !mov temp&,ecx              'transfer the byte to the FPU
                            !fmul st(0),st(1)           'update the fractional multiplier
                            
                            !fild temp&                 'get digit
                            !fmul st(0),st(1)           'scale the digit
                            !faddp st(3),st(0)          'add the scaled digit to the current fraction and pop the digit
                            
                            !jmp short lp2              'go back for next character
                            
                            skip2:
                            !fstp st(0)             'clear the scale off the stack
                            !fstp st(0)             'clear the scale multiplier off the stack
                            !faddp st(1),st(0)      'add the fraction to the integer and pop the fraction
                            
                            skip:
                            !fchs           'change the sign before storing answer
                            !fstp answer##  'save the answer
                            
                            !fstp st(0)     'clear the "10" off the FPU stack
                            
                            
                            TIX END t&&
                            PRINT "time="t&&
                            PRINT answer##
                            
                            WAITKEY$
                            
                            END FUNCTION
                            Paul.

                            Comment


                            • #15
                              Very nice, Paul.
                              I turned it into a function for him and ran a few tests.

                              Code:
                                #REGISTER NONE
                               
                                FUNCTION PBMAIN () AS LONG
                                DO
                                  INPUT "Number ";s$
                                  IF LEN(s$) = 0 THEN EXIT DO
                                  REPLACE "-" WITH "" IN s$
                                  e## = ExtNumber(s$)
                                  ? STR$(e##)
                                LOOP
                                END FUNCTION
                               
                              FUNCTION ExtNumber(s AS STRING) AS EXT
                               
                               'Paul Dixon code  2/6/09 
                               ' [URL]http://www.powerbasic.com/support/pbforums/showthread.php?t=39802[/URL]
                               
                               LOCAL MyNumber AS ASCIIZ *100
                               LOCAL Ten    AS SINGLE
                               LOCAL tenth  AS EXT
                               LOCAL Temp   AS LONG
                               LOCAL Answer AS EXT
                               MyNumber = s  'added line, you can pass MyNumber AS ASCIIZ *100
                               ten!=10
                               tenth##=1/10##
                               temp&=0
                               answer##=0
                               
                              !lea eax,MyNumber       'get address of string, it's zero terminated
                              !fld ten!               'some useful values for the FPU, 10
                              !fldz                   ' zero (the initial value for the answer)
                              'do the integer part
                              lp:
                              !movzx ecx,byte ptr [eax]   'get current byte
                              !inc eax                    'point to next byte
                              !cmp cl,0                   'is current byte zero? (end of string)
                              !je skip                    'yes, exit
                              !cmp cl,"."                 'is it a decimal point?
                              !je fraction                'yes, do the fraction part
                               
                              !sub ecx,"0"                'no, convert ascii character to binary
                              !mov temp&,ecx              'transfer the byte to the FPU
                              !fmul st(0),st(1)           'multiply answer so far by 10
                              !fild temp&                 'get digit
                              !faddp st(1),st(0)          'add it in to the answer
                              !jmp short lp               'go back for next character
                              fraction:
                              !fldz                       'start the fractional part off at zero
                              !fld tenth##                'some useful values for the FPU, 1/10 (the scale for the fractional multiplier)
                              !fld1                       ' 1  (the fractional mutiplier)
                               
                              lp2:
                              !movzx ecx,byte ptr [eax]   'get current byte
                              !inc eax                    'point to next byte
                              !cmp cl,0                   'is current byte zero? (end of string)
                              !je skip2                    'yes, exit
                              !sub ecx,"0"                'no, convert ascii character to binary
                              !mov temp&,ecx              'transfer the byte to the FPU
                              !fmul st(0),st(1)           'update the fractional multiplier
                              !fild temp&                 'get digit
                              !fmul st(0),st(1)           'scale the digit
                              !faddp st(3),st(0)          'add the scaled digit to the current fraction and pop the digit
                              !jmp short lp2              'go back for next character
                              skip2:
                              !fstp st(0)             'clear the scale off the stack
                              !fstp st(0)             'clear the scale multiplier off the stack
                              !faddp st(1),st(0)      'add the fraction to the integer and pop the fraction
                              skip:
                              !fchs           'change the sign before storing answer
                              !fstp answer##  'save the answer
                              !fstp st(0)     'clear the "10" off the FPU stack
                              FUNCTION = answer
                              END FUNCTION
                              Last edited by Mike Doty; 6 Feb 2009, 08:32 PM. Reason: Cosmetic

                              Comment


                              • #16
                                >assumes the string is +ve and has only characters 0 to 9 and decimal point

                                That's one of the problems with these 'peformance enhancements'

                                The fact the data are stored as character strings without the correct sign suggests it is data not created by the application.....meaning it SHOULD be edited.. meaning perforce string operations are going to be required and negation will be but a tiny portion of the total processing time required anyway.

                                With faster negation code but no editing, you're just asking for faster "garbage out."
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17
                                  Waw !!! I'm impressed with the work you've all put in this. I got away for some 'hours' and a lot of stuff has been put into this.

                                  Yes, there is more to this. It is part of a modified version of the Reverse Polish Notation algorithm that I'm using. The RPN parser doesn't know the difference between and operator (-) and a negative sign (-) hence I have to store it using a byte in a structure that indicates that the number is negative but then to solve the RPN I have to check for the negative-ness of a number. As everything is represented as a string (by design and because of the need for it). I requested a fast method to make a string number into negative Extended value.

                                  Thanks to everyone who has put thought and work into this
                                  So here we are, this is the end.
                                  But all that dies, is born again.
                                  - From The Ashes (In This Moment)

                                  Comment


                                  • #18
                                    Michael, why do you preach? He asked for this and got it.
                                    Last edited by Mike Doty; 7 Feb 2009, 03:20 PM.

                                    Comment


                                    • #19
                                      >why do you preach?

                                      Because the only thing of real value any of us leave behind is the next generation.
                                      Michael Mattias
                                      Tal Systems (retired)
                                      Port Washington WI USA
                                      [email protected]
                                      http://www.talsystems.com

                                      Comment


                                      • #20
                                        Why not create a thread of your own?

                                        Comment

                                        Working...
                                        X