Sign in Join
Wiki copytemporary

Base converting: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11The following [[Unit|unit]] will allow you to convert from one number base to another. Each base is chosen in the range `2..36`.
22
33Note, the unit does not know a negative sign.
44
55## Source
66
77``` pascal
88unit baseConvert;
99
1010// for exceptions
1111{$mode objfpc}
1212
1313// P U B L I C ======================================================== //
1414interface
1515
1616const
1717 /// list of symbols for integer representations
1818 digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
1919
2020function intToBaseStr(value: longword; const base: cardinal = 10): string;
2121function baseStrToInt(const value: string; const base: cardinal = 10): longword;
2222
2323function baseToBase(
2424 const value: string;
2525 const interpretation: cardinal = 10;
2626 const base: cardinal = 10
2727 ): string;
2828
2929
3030// P R I V A T E ====================================================== //
3131implementation
3232
3333uses
3434 // math unit for inRange and divMod routines
3535 math,
3636 // sysutils unit for ERangeError exception
3737 sysutils;
3838
3939resourceString
4040 /// base not within range of available symbols
4141 errInvalidBase = '↯ b = %0:d! ⇒ b ∉ [%1:d, %2:d]';
4242 /// supplied character not within domain
4343 errInvalidSymbol = '↯ v(''%0:s'')↑; b = %1:d';
4444
4545(**
4646 \brief expresses the value in the desired base
4747
4848 \param value the value to convert
4949 \param base
5050
5151 \return a string representing the number in given base
5252*)
5353function intToBaseStr(value: longword; const base: cardinal = 10): string;
5454var
5555 remainder: longword;
5656begin
5757 // validity of the base
5858 if not inRange(base, 2, length(digits)) then
5959 begin
6060 raise eRangeError.createFmt(errInvalidBase, [base, 2, length(digits)]);
6161 end;
6262
6363 // decomposing the value: reverse Horner-scheme
6464 // The repeat-statement takes the value 0 into account.
6565 result := emptyStr;
6666 repeat
6767 begin
6868 divMod(value, base, value, remainder);
6969 // prepend value: intermediate results are read backwards
7070 result := digits[remainder + 1] + result;
7171 end
7272 until value = 0;
7373end;
7474
7575(**
7676 \brief transforms the string of a number
7777 expressed in the parameter base
7878 into the equivalent integer
7979
8080 \param value the representation of the integer
8181 \param base assume string is in given base
8282
8383 If the string is empty, the result is 0.
8484
8585 Caution:
8686 No verification of integer overflows.
8787 Reasonable values have to be used.
8888
8989 \return the integer
9090*)
9191function baseStrToInt(const value: string; const base: cardinal = 10): longword;
9292var
9393 symbol: char;
9494 // beware, cardinal is _non-negative_
9595 digit: cardinal;
9696begin
9797 result := 0;
9898 // Horner-scheme
9999 for symbol in value do
100100 begin
101101 // determine ordinal value of current symbol
102102 digit := pos(symbol, digits);
103103 // If symbol wasn't found, pos returns 0.
104104 // Or possibly the symbol isn't known in the base.
105105 if not inRange(digit, 1, base) then
106106 begin
107107 raise eRangeError.createFmt(errInvalidSymbol, [symbol, base]);
108108 end;
109109 // e.g. the symbol '0' is the _first_ character in digits
110110 // thus the pos function returned 1 => here we subtract one
111111 dec(digit);
112112 result := result * base + digit;
113113 end;
114114end;
115115
116116(**
117117 \brief direct conversion of number expressed in one base to another
118118
119119 \param value the value to convert from
120120 \param interpretation the base to interpret the value as
121121 \param base the base to convert to
122122*)
123123function baseToBase(
124124 const value: string;
125125 const interpretation: cardinal = 10;
126126 const base: cardinal = 10
127127 ): string;
128128begin
129129 // the case interpretation = base
130130 // intentionally does not have special treatment for unit tests
131131 result := intToBaseStr(baseStrToInt(value, interpretation), base);
132132end;
133133
134134// end of unit
135135end.
136136```
137137
138138## Remarks
139139
140140For your information: For bases two, eight, ten, and sixteen, you can use `binStr`, `OctStr`, `str` and `hexStr` from the automatically included `system` unit.
141141
142142## Locales
143143
144-`en.po` <small>
144+`en.po`
145145
146146``` bash
147147#: baseconvert:errinvalidbase
148148msgid "\342\206\257\302\240b\302\240= %0:d!\302\240\342\207\222 b\302\240\342\210\211\302\240[%1:d, %2:d]"
149149msgstr "Base %0:d is invalid. It must be between %1:d and %2:d."
150150
151151#: baseconvert:errinvalidsymbol
152152msgid "\342\206\257\302\240v('%0:s')\342\206\221; b\302\240= %1:d"
153153msgstr "The symbol '%0:s' has an unacceptable value for base = %1:d."
154154```
155155
156-</small>
157-
158-`de.po` <small>
156+`de.po`
159157
160158``` bash
161159#: baseconvert:errinvalidbase
162160msgid "\342\206\257\302\240b\302\240= %0:d!\302\240\342\207\222 b\302\240\342\210\211\302\240[%1:d, %2:d]"
163161msgstr "Die Basis %0:d ist ungültig. Sie muß zwischen %1:d und %2:d sein."
164162
165163#: baseconvert:errinvalidsymbol
166164msgid "\342\206\257\302\240v('%0:s')\342\206\221; b\302\240= %1:d"
167165msgstr "Der Zeichenwert von '%0:s' ist ungültig für Zahlen der Basis %1:d."
168166```
169167
170-</small>
171-
172-`fr.po`: <small>
168+`fr.po`:
173169
174170``` bash
175171#: baseconvert:errinvalidbase
176172msgid "\342\206\257\302\240b\302\240= %0:d!\302\240\342\207\222 b\302\240\342\210\211\302\240[%1:d, %2:d]"
177173msgstr "Base %0:d invalide, elle doit être comprise entre %1:d et %2:d."
178174
179175#: baseconvert:errinvalidsymbol
180176msgid "\342\206\257\302\240v('%0:s')\342\206\221; b\302\240= %1:d"
181177msgstr "Mauvais chiffre '%0:s' dans la valeur, base = %1:d."
182178```
183-
184-</small>
185179
186180## More ...
187181
188182A more elaborate implementation (based upon the example code above) can be found in [this FsiConv unit](http://svn.code.sf.net/p/flyingsheep/code/trunk/MijnLib/fsiconv.pp).\
189183It has implementations for all integer types (signed and unsigned) as well as TryStrToXXX and StrToXXXDef functions.
190184
191185---
192186*From the Free Pascal wiki, page "Base converting", as it stood on 2022-05-26 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history