source: trunk/Include/Classes/ActiveBasic/Strings/SPrintF.ab@ 335

Last change on this file since 335 was 335, checked in by イグトランス (egtra), 17 years ago

SPrintF関連の追加。関数FloatToChars, FormatFloatE, FormatIntegerUと列挙体FormatFlags。

File size: 5.2 KB
Line 
1'Classes/ActiveBasic/Strings/SPrintF.ab
2
3Namespace ActiveBasic
4Namespace Strings
5
6Namespace Detail
7
8/*!
9@brief 浮動小数点数を文字列化する低水準な関数。符号、指数、仮数に分けて出力。
10@author Egtra
11@date 2007/09/18
12@param[in] x 文字列化する浮動小数点数
13@param[out] e 指数
14@param[out] sign 符号
15@return 仮数
16仮数は1の位から下へ17桁で、小数点を含まない。そのため、誤差を無視すればVal(仮数) * 10 ^ (e - 17) = Abs(x)が成り立つ。
17
18xに無限大、無限小、非数を渡した場合の動作は未定義。
19*/
20Function FloatToChars(x As Double, ByRef e As Long, ByRef sign As Boolean) As String
21 Imports System
22
23 '0を弾く
24 If x = 0 Then
25 If GetQWord(VarPtr(x) As *QWord) And &h8000000000000000 Then
26 sign = True
27 Else
28 sign = False
29 End If
30
31 e = 0
32 FloatToChars = "00000000000000000"
33 Exit Function
34 End If
35
36 '符号の判断(同時に符号を取り除く)
37 If x < 0 Then
38 sign = True
39 x = -x
40 Else
41
42 sign = False
43 End If
44
45 '1e16 <= x < 1e17へ正規化
46 '(元のx) = (正規化後のx) ^ (d - 17)である。
47 Dim d = Math.Floor(Math.Log10(x)) As Long
48 If d < 16 Then
49 x *= ipow(10, +17 - d)
50 ElseIf d > 16 Then
51 x /= ipow(10, -17 + d)
52 End If
53
54 '補正
55 While x < 1e16
56 x *= 10
57 d--
58 Wend
59 While x >= 1e17
60 x /= 10
61 d++
62 Wend
63
64 d--
65 e = d
66
67 FloatToChars = Str$(x As QWord)
68End Function
69
70/*!
71@brief 書式化関数群で使用するフラグ。
72@author Egtra
73@date 2007/09/18
74*/
75Const Enum FormatFlags
76 '! 何も指定がない。
77 None = &h0
78 '! 符号、+。符号付変換[diAaEeFfGg]のとき、正の値でも符号を付ける。
79 Sign = &h1
80 /*! 空白、空白文字。
81 符号付変換[diAaEeFfGg]のとき、正の値ならば符号分の空白を開ける。Signが立っているときには無視される。
82 */
83 Blank = &h2
84 /*! ゼロ、0。
85 [diouXxAaEeFfGg]で、フィールドの空きを0で埋める。leftが立っているときには無視される。
86 */
87 Zero = &h4
88 '! 左揃え、-。フィールド内で左揃えにする。
89 Left = &h8
90 /*! 代替表記、#。
91 <ul>
92 <li>[OoXx]では、数値の先頭に0、0xを付ける。</ul>
93 <li>[AaEeFfGg]では、精度0でも小数点を付ける。</ul>
94 <li>[Gg]では、それに加え、小数部末尾の0の省略を行わないようにする。</ul>
95 </ul>
96 */
97 Alt = &h10
98 '! 大文字。使用するアルファベットを大文字にする。[aefgx]を[AEFGX]化する。
99 Cap = &h20
100End Enum
101
102/*!
103@brief 浮動小数点数をprintfの%e, %E相当の変換で文字列化する関数。
104@author Egtra
105@date 2007/09/18
106@param[in] x 文字列化する浮動小数点数値。
107@param[in] d 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。
108@param[in] field フィールド幅。
109@param[in] flags 書式フラグ。
110@return xの文字列表現
111
112@todo 末尾桁四捨五入
113*/
114Function FormatFloatE(x As Double, d As DWord, field As DWord, flags As FormatFlags) As String
115 Dim sb = New System.Text.StringBuilder
116 With sb
117 If d = DWORD_MAX Then
118 d = 6
119 End If
120
121 Dim e As Long, sign As Boolean
122 Dim s = FloatToChars(x, e, sign)
123
124 If sign Then
125 .Append("-")
126 Else
127 If flags And Sign Then
128 .Append("+")
129 ElseIf flags And Blank Then
130 .Append(" ")
131 End If
132 End If
133
134 .Append(s[0])
135
136 If (flags And Alt) Or d > 0 Then
137 .Append(".")
138 Dim outputLen = s.Length - 1
139 If outputLen >= d Then
140 .Append(s, 1, d)
141 Else 'sで用意された桁が指定された精度より少ないとき
142 .Append(s, 1, outputLen)
143 .Append(&h30 As StrChar, d - outputLen) '足りない桁は0埋め
144 End If
145 End If
146
147 If flags And Cap Then
148 .Append("E")
149 Else
150 .Append("e")
151 End If
152
153 Dim buf[1023] As TCHAR
154 wsprintf(buf, "%03d", e)' "%+03d", e) wsprintfは+フラグが使えない!
155 Dim ts = New String(buf, 3)
156 .Append(ts)
157 '.Append(FormatLongD(e, 3, 0, Sign)
158
159 If .Length < field Then
160 Dim embeddedSize = .Length - field
161 If flags And Left Then
162 .Append(&h20, embeddedSize)
163 Else
164 Dim insPos As Long
165 If flags And Blank Then
166 insPos++
167 End If
168 .Insert(insPos, String$(embeddedSize, " "))
169 End If
170 End If
171 End With
172 FormatFloatE = sb.ToString()
173End Function
174
175'! DWordの最大値4294967295の文字数 - 1。FormatIntegerU内で使用。
176Const MaxSize = 9
177
178/*!
179@brief 符号無し整数をprintfの%u相当の変換で文字列化する関数。
180@author Egtra
181@date 2007/09/18
182@param[in] x 文字列化する整数値。
183@param[in] d 精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。
184@param[in] field フィールド幅。
185@param[in] flags 書式フラグ。
186@return xの文字列表現
187*/
188Function FormatIntegerU(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String
189 'zero, left
190
191 '左揃えのときまたは精度が指定されているとき、ゼロフラグは無視される。
192 If (flags And Left) Or (d <> DWORD_MAX) Then
193 flags And= Not Zero
194 End If
195
196 If d = DWORD_MAX Then
197 d = 1
198 End If
199
200 Dim sb = New System.Text.StringBuilder
201 With sb
202 Dim buf[MaxSize] As StrChar
203 Dim i = MaxSize
204 While x <> 0
205 buf[i] = (x As Int64 Mod 10 + &h30) As StrChar 'Int64への型変換は#117対策
206 x \= 10
207 i--
208 Wend
209
210 Dim len = (MaxSize - i) As Long
211 If len < d Then
212 .Append(&h30 As StrChar, d - len)
213 End If
214
215 .Append(buf, i + 1, len)
216
217 If field > len Then
218 Dim embeddedSize = field - len
219 If flags And Left Then
220 .Append(&h20, embeddedSize)
221 Else
222 .Insert(0, String$(embeddedSize, " "))
223 End If
224 End If
225 End With
226 FormatIntegerU = sb.ToString()
227End Function
228
229End Namespace 'Detail
230
231End Namespace 'Strings
232End Namespace 'ActiveBasic
Note: See TracBrowser for help on using the repository browser.