Difference between revisions of "Base converting"
From Free Pascal wiki
Jump to navigationJump to searchm (→locales) |
m (Replace deprecated enclose attributes) |
||
(One intermediate revision by one other user not shown) | |||
Line 2: | Line 2: | ||
{{Base_converting}} | {{Base_converting}} | ||
− | The following [[Unit|<syntaxhighlight lang="pascal" | + | The following [[Unit|<syntaxhighlight lang="pascal" inline>unit</syntaxhighlight>]] will allow you to convert from one number base to another. |
− | Each base is chosen in the range <syntaxhighlight lang="pascal" | + | Each base is chosen in the range <syntaxhighlight lang="pascal" inline>2..36</syntaxhighlight>. |
Note, the unit does not know a negative sign. | Note, the unit does not know a negative sign. | ||
− | == | + | == Source == |
<syntaxhighlight lang="pascal" line> | <syntaxhighlight lang="pascal" line> | ||
unit baseConvert; | unit baseConvert; | ||
Line 139: | Line 139: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | == | + | == Remarks == |
+ | |||
For your information: | For your information: | ||
For bases two, eight, ten, and sixteen, you can use <code>binStr</code>, <code>OctStr</code>, <code>str</code> and <code>hexStr</code> from the automatically included <code>system</code> unit. | For bases two, eight, ten, and sixteen, you can use <code>binStr</code>, <code>OctStr</code>, <code>str</code> and <code>hexStr</code> from the automatically included <code>system</code> unit. | ||
− | == | + | == Locales == |
+ | |||
<tt>en.po</tt> | <tt>en.po</tt> | ||
<small><syntaxhighlight lang="bash"> | <small><syntaxhighlight lang="bash"> | ||
Line 176: | Line 178: | ||
msgstr "Mauvais chiffre '%0:s' dans la valeur, base = %1:d." | msgstr "Mauvais chiffre '%0:s' dans la valeur, base = %1:d." | ||
</syntaxhighlight></small> | </syntaxhighlight></small> | ||
+ | |||
+ | == More ... == | ||
+ | |||
+ | A more elaborate implementation (based upon the example code above) can be found in [http://svn.code.sf.net/p/flyingsheep/code/trunk/MijnLib/fsiconv.pp this FsiConv unit].<br> | ||
+ | It has implementations for all integer types (signed and unsigned) as well as TryStrToXXX and StrToXXXDef functions. |
Latest revision as of 10:07, 26 May 2022
│
English (en) │
français (fr) │
The following unit
will allow you to convert from one number base to another.
Each base is chosen in the range 2..36
.
Note, the unit does not know a negative sign.
Source
1unit baseConvert;
2
3// for exceptions
4{$mode objfpc}
5
6// P U B L I C ======================================================== //
7interface
8
9const
10 /// list of symbols for integer representations
11 digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
12
13function intToBaseStr(value: longword; const base: cardinal = 10): string;
14function baseStrToInt(const value: string; const base: cardinal = 10): longword;
15
16function baseToBase(
17 const value: string;
18 const interpretation: cardinal = 10;
19 const base: cardinal = 10
20 ): string;
21
22
23// P R I V A T E ====================================================== //
24implementation
25
26uses
27 // math unit for inRange and divMod routines
28 math,
29 // sysutils unit for ERangeError exception
30 sysutils;
31
32resourceString
33 /// base not within range of available symbols
34 errInvalidBase = '↯ b = %0:d! ⇒ b ∉ [%1:d, %2:d]';
35 /// supplied character not within domain
36 errInvalidSymbol = '↯ v(''%0:s'')↑; b = %1:d';
37
38(**
39 \brief expresses the value in the desired base
40
41 \param value the value to convert
42 \param base
43
44 \return a string representing the number in given base
45*)
46function intToBaseStr(value: longword; const base: cardinal = 10): string;
47var
48 remainder: longword;
49begin
50 // validity of the base
51 if not inRange(base, 2, length(digits)) then
52 begin
53 raise eRangeError.createFmt(errInvalidBase, [base, 2, length(digits)]);
54 end;
55
56 // decomposing the value: reverse Horner-scheme
57 // The repeat-statement takes the value 0 into account.
58 result := emptyStr;
59 repeat
60 begin
61 divMod(value, base, value, remainder);
62 // prepend value: intermediate results are read backwards
63 result := digits[remainder + 1] + result;
64 end
65 until value = 0;
66end;
67
68(**
69 \brief transforms the string of a number
70 expressed in the parameter base
71 into the equivalent integer
72
73 \param value the representation of the integer
74 \param base assume string is in given base
75
76 If the string is empty, the result is 0.
77
78 Caution:
79 No verification of integer overflows.
80 Reasonable values have to be used.
81
82 \return the integer
83*)
84function baseStrToInt(const value: string; const base: cardinal = 10): longword;
85var
86 symbol: char;
87 // beware, cardinal is _non-negative_
88 digit: cardinal;
89begin
90 result := 0;
91 // Horner-scheme
92 for symbol in value do
93 begin
94 // determine ordinal value of current symbol
95 digit := pos(symbol, digits);
96 // If symbol wasn't found, pos returns 0.
97 // Or possibly the symbol isn't known in the base.
98 if not inRange(digit, 1, base) then
99 begin
100 raise eRangeError.createFmt(errInvalidSymbol, [symbol, base]);
101 end;
102 // e.g. the symbol '0' is the _first_ character in digits
103 // thus the pos function returned 1 => here we subtract one
104 dec(digit);
105 result := result * base + digit;
106 end;
107end;
108
109(**
110 \brief direct conversion of number expressed in one base to another
111
112 \param value the value to convert from
113 \param interpretation the base to interpret the value as
114 \param base the base to convert to
115*)
116function baseToBase(
117 const value: string;
118 const interpretation: cardinal = 10;
119 const base: cardinal = 10
120 ): string;
121begin
122 // the case interpretation = base
123 // intentionally does not have special treatment for unit tests
124 result := intToBaseStr(baseStrToInt(value, interpretation), base);
125end;
126
127// end of unit
128end.
Remarks
For your information:
For bases two, eight, ten, and sixteen, you can use binStr
, OctStr
, str
and hexStr
from the automatically included system
unit.
Locales
en.po
#: baseconvert:errinvalidbase
msgid "\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]"
msgstr "Base %0:d is invalid. It must be between %1:d and %2:d."
#: baseconvert:errinvalidsymbol
msgid "\342\206\257\302\240v('%0:s')\342\206\221; b\302\240= %1:d"
msgstr "The symbol '%0:s' has an unacceptable value for base = %1:d."
de.po
#: baseconvert:errinvalidbase
msgid "\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]"
msgstr "Die Basis %0:d ist ungültig. Sie muß zwischen %1:d und %2:d sein."
#: baseconvert:errinvalidsymbol
msgid "\342\206\257\302\240v('%0:s')\342\206\221; b\302\240= %1:d"
msgstr "Der Zeichenwert von '%0:s' ist ungültig für Zahlen der Basis %1:d."
fr.po:
#: baseconvert:errinvalidbase
msgid "\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]"
msgstr "Base %0:d invalide, elle doit être comprise entre %1:d et %2:d."
#: baseconvert:errinvalidsymbol
msgid "\342\206\257\302\240v('%0:s')\342\206\221; b\302\240= %1:d"
msgstr "Mauvais chiffre '%0:s' dans la valeur, base = %1:d."
More ...
A more elaborate implementation (based upon the example code above) can be found in this FsiConv unit.
It has implementations for all integer types (signed and unsigned) as well as TryStrToXXX and StrToXXXDef functions.