Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
-Delphi/Pascal
-CBuilder/C++
-C#Builder/C#
-JBuilder/Java
-Kylix
Member Area
-Home
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Login/Logout
-Become a Member
-Why sign up!
-Newsletter
-Chat Online!
-Indexes NEW!!
Employment
-Build your resume
-Find a job
-Post a job
-Resume Search
Contacts
-Contacts
-Feedbacks
-Link to us
-Privacy/Disclaimer
Embarcadero
Visit Embarcadero
Embarcadero Community
JEDI
Links
Num2Str() function Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
Faster conversion of an integer to a string, than Format() 22-Aug-05
Category
N/A
Language
Delphi All Versions
Views
192
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
Nemitz, Vernon
Reference URL:
			1   // A version of Delphi that supports in-line assembly language
2   //  is required (Enterprise or maybe Professional)
3   
4   // Convert Base-Ten whole Number to string, with minimal string-
5   //  space usage, faster than Format(), and Thread-Safe.
6   // Width and Precision lengths can be specified or zero (ignored
7   //  if zero); WIDTH IS A FIXED FIELD SIZE; padding
8   // spaces are added if Number is smaller; use negative Width to
9   //  left-justify Number; a too-long Number has its
10  // Least Significant Digits truncated; a minus sign can cost
11  //  another Digit (YOU must ensure Width is big enough!)
12  // PRECISION IS A MINIMUM NUMBER SIZE; takes precedence over
13  //  Width if Width is smaller; adds leading zeros if Number
14  //  is smaller; a negative Precision causes truncation of Most
15  //  Significant Digits if Number is bigger than Width
16    function Num2Str(w, p, n: Integer): string;
17      var
18        i, j, k: Integer;
19      begin
20  //    Result := Format('%*.*d', [w, p, n]); // MOST of what this
21                                              // function does can
22                                              // be handled by this
23                                              // one line. Usually
24                                              // that one line will
25                                              // be adequate.  But
26                                              // the innards of
27                                              // Format() are MUCH
28                                              // more complex than
29                                              // below, and thus
30                                              // are rather slower.
31        i := 0;          // initialize a digits-on-stack counter
32        j := 0;          // future flag
33        k := 0;          // future length-adjustment value
34        asm
35          MOV  EAX, n    // get number we want to convert
36                         //  (low-order part of 64-bit dividend)
37          or   EAX, EAX  // set flags (MOV affects no flags)
38          JGE  @@skp1    // skip if a positive number (Greater than
39                         //  or Equal to zero)
40          INC  j         // indicate later need for a minus sign
41          INC  k         // adustment=1: a negative number, of
42                         //  course, consists of at least a minus
43                         //  sign and a digit
44          NEG  EAX       // negate a negative (make positive)
45  @@skp1: MOV  ECX, 10   // set a divisor: ten
46  @@mor:  MOV  EDX, 0    // erase high-order portion of 64-bit
47                         //  dividend
48          div  ECX       // divide 32 bits into 64, quotient in
49                         //  EAX, remainder in EDX
50          PUSH EDX       // save the remainder on the stack
51                         //  (last-to-1st digit of future string)
52          INC  i         // increase count of digits (quotient
53                         //  always has at least one)
54          or   EAX, EAX  // set flags
55          JNZ  @@mor     // if any digits not placed one-at-a-time
56                         //  on stack, loop to do another
57          MOV  EAX, w    // get Width
58          or   EAX, EAX  // set flags
59          JZ   @@ign1    // ignore if zero
60          JG   @@pos1    // already positive?
61          NEG  EAX       // negate a negative (make positive)
62  @@pos1: SUB  EAX, i    // compute a difference in lengths
63          MOV  k, EAX    // set length-adjustment (accommodates
64                         //  extra space or truncation, minus sign
65                         //  INCLUDED)
66  @@ign1: MOV  ECX, i    // get length of Number
67          MOV  EAX, p    // get Precision
68          MOV  EDX, EAX  // copy it
69          or   EAX, EAX  // set flags...
70          JZ   @@ok1     // OK to ignore if no Precision
71          JG   @@pos2    // already positive?
72          NEG  EAX       // convert negative into positive
73          MOV  EDX, EAX  // copy Precision again
74  @@pos2: SUB  EAX, ECX  // compute a difference
75          CMP  EAX, k    // compare Precision-Number difference
76                         //  with Width-Number difference
77          JLE  @@ok1     // if Precision is Less than or Equal to
78                         //  Width, OK!
79          MOV  k, EAX    // replace prior difference with one that
80                         //  takes precedence
81  @@ok1:  PUSH EDX       // save absolute value of (modified)
82                         //  Precision on the stack
83          ADD  ECX, k    // i + k
84          PUSH ECX       // save it on the stack
85        end;
86        Result := StringOfChar(' ', (i + k));  // create string of
87                                               //  correct final
88                                               //  length (Format()
89                                               //  concatenates)
90        asm
91          POP  ECX         // recover last value PUSHed onto stack:
92                           //  i + k
93          SUB  ECX, j      // now account for possible minus sign
94          MOV  k, ECX      // save that quantity of SPACE for
95                           //  allowed digits
96          MOV  EAX, i      // get length of Number
97          MOV  EDX, [ESP]  // get absolute value of precision
98                           //  (keep it on stack)
99          CMP  EAX, EDX    // compare two possibly-different
100                          //  lengths
101         JAE  @@ok2       // if Above or Equal, length of Number
102                          //  is OK
103         MOV  EAX, EDX    // precision is longer than Number, so
104                          //  leading zeros will be added
105 @@ok2:  CMP  EAX, ECX    // compare two possibly-different
106                          //  lengths
107         JA   @@trc2      // if Number is Above i+k, truncation
108                          //  will happen
109         MOV  k, EAX      // set k to the Number's length
110                          //  (it fits!)
111         JE   @@trc2      // go start at string element 0 if
112                          // Number exactly fits in string
113 @@trc1: MOV  EAX, w      // get width
114         or   EAX, EAX    // set flags (test for left-justify)
115         JL   @@trc2      // like truncation, left-justify starts
116                          //  at element 0 (see jump destination)
117         SUB  ECX, i      // get difference between string's and
118                          //  Number's lengths
119         MOV  EAX, ECX    // save possible index to
120                          //  (right-justified) first
121                          //  string-element we'll access
122         JA   @@ok3       // OK if string actually long enough
123                          //  even for a negative Number
124 @@trc2: MOV  EAX, 0      // initialize a string-index counter
125                          //  (in Assembly Language,
126                          //  1st element is 0)
127 @@ok3:  MOV  EDX, Result // prepare to dump data into Result
128                          //  string
129         MOV  EDX, [EDX]  // finish getting the address of that
130                          //  string
131         MOV  ECX, j      // get minus-sign indicator
132         or   ECX, ECX    // test it
133         JZ   @@skp2      // skip if positive
134         MOV  byte ptr [EDX + EAX], '-' // put the minus sign into
135                                        //  the string
136         INC  EAX         // increment the index
137 @@skp2: MOV  ECX, k      // quantity of digits we'll be putting
138                          //  into string, even if truncating
139         SUB  ECX, i      // compute quantity of digits we'll be
140                          //  truncating, as a negative value
141         MOV  w, ECX      // save as a Most-Sig-Digits truncation
142                          //  counter
143         MOV  ECX, p      // get Precedence
144         or   ECX, ECX    // set flags to test for Most/Least
145                          //  Sig-Digit truncation
146         JL   @@skp3      // a negative value means we'll truncate
147                          //  Most Significant Digits
148         MOV  w, ECX      // replace the negative value in w with
149                          //  a positive value
150 @@skp3: POP  ECX         // recover absolute value of Precision
151                          //  from stack
152         SUB  ECX, j      // remove previously-included space for
153                          //  minus sign
154         JZ   @@loop      // no Precision specified (no leading
155                          //  zeros or Most-Sig-Digits truncation)
156         SUB  ECX, i      // compute number of possible leading
157                          //  zeros for Number
158         JLE  @@loop      // skip if none
159 @@zero: MOV  byte ptr [EDX + EAX], '0' // put a leading zero into
160                                        //  the string
161         INC  EAX         // increment the index
162         DEC  ECX         // decrement number of leading zeros
163         JNE  @@zero      // loop til necessary quantity are
164                          //  embedded in string
165         JMP  @@loop      // skip the DEC (faster than
166                          //  precompensating for it with INC)
167 @@sync: DEC  i           // countdown an about-to-be-removed
168                          //  digit from the stack
169 @@loop: POP  ECX         // get a digit (first to last) off the
170                          //  stack
171         INC  w           // count possible Most-Sig-Digit
172                          //  truncation
173         JLE  @@sync      // if still Less than or Equal to zero,
174                          //  we ARE truncating Most-Sig-Digits
175         DEC  k           // countdown quantity of allowed digits,
176                          //  before Least-Sig-Digits truncation
177         JL   @@skp4      // skip when this countdown passes zero
178         ADD  CL, '0'     // convert from numeral to ASCII
179                          //  character
180         MOV  byte ptr [EDX + EAX], CL  // put the character into
181                                        //  the Result string
182         INC  EAX         // increment the string-index-counter
183 @@skp4: DEC  i           // decrement the remaining quantity of
184                          //  digits on the stack
185         JNE  @@loop      // if Not Equal to zero, loop to convert
186                          //  those remaining digits
187       end;
188     end;


			
Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10

 

Advertisement
Share this page
Advertisement
Download from Google

Copyright © Mendozi Enterprises LLC