File: bigfloat.man

package info (click to toggle)
tcllib 1.8-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 13,628 kB
  • ctags: 4,897
  • sloc: tcl: 88,012; sh: 7,856; ansic: 4,174; xml: 1,765; yacc: 753; perl: 84; f90: 84; makefile: 60; python: 33; ruby: 13; php: 11
file content (327 lines) | stat: -rwxr-xr-x 12,192 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
[manpage_begin math::bigfloat n 1.2]
[copyright {2004-2005 Stephane Arnold <stephanearnold at yahoo dot fr>}]
[moddesc   {Tcl Math Library}]
[titledesc {Arbitrary precision floating-point numbers}]

[require Tcl [opt 8.4]]
[require math::bignum [opt 3.0]]
[require math::bigfloat [opt 1.2]]

[description]

The bigfloat package provides arbitrary precision floating-point math
capabilities to the Tcl language.
By convention, we will talk about the numbers treated in this library as :
[list_begin bullet]
[bullet]BigFloat for floating-point numbers of arbitrary length
[bullet]BigInt for arbitrary length signed integers (a.k.a. bignums)
[list_end]
BigFloats are internally represented at Tcl lists: this
package provides a set of procedures operating against
the internal representation in order to :
[list_begin bullet]
[bullet]
perform math operations on either BigFloats or BigInts.

[bullet]
convert BigFloats and BigInts from the internal representation to a string, and vice versa.

[list_end]

[section "INTRODUCTION"]
[list_begin definitions]

[call [cmd fromstr] [arg string] [opt [arg trailingZeros]]]
Converts [emph string] into a BigFloat, or a BigInt. Its precision
is at least the number of digits provided by [emph string].
If the [arg string] contains only digits and eventually a minus sign, it is considered as
an integer.
[nl]
[arg trailingZeros] - the number of zeros to append at the end of the floating-point number
to get more precision from the [emph string]. When applied on an integer, it throws an error.

[call [cmd fromstr] -base [arg radix] [arg string]]
Converts [emph string] representing an integer in the base [emph radix], to a BigInt.
[example_begin]
set x [lb]fromstr -1.000000[rb]
set y [lb]fromstr 2000e30[rb]
# x and y are BigFloats : the first string contained a dot, and the second an e sign
set m [lb]fromstr 1000[rb]
set n [lb]fromstr -39[rb]
# m and n are BigInts because the original string contained neither a dot nor an e sign
# negative BigInts are supported
set octalNumber [lb]fromstr -base 8 377[rb]
# the result is 377 in octal, so it is equal to 255
[example_end]
[nl]
The [emph string]'s last digit is considered by the procedure to be true at +/-1.
For instance, the Pi constant is irrational, so as you feed in the string "3.1415"
it may be considered as a number in the interval [lb]3.1414 , 3.1416[rb].
This is why we call such mathematics [emph "interval computations"].
For example, 0.1 belongs to the interval [lb]0.0, 0.2[rb],
and 1.00 to the interval [lb]0.99,1.01[rb].So, when you mean 1.0, you may have to write 1.000000 to get enough precision.
If you encounter problems with precision, I recommend you read [sectref PRECISION].
[nl]
For example :
[example_begin]
set x [lb]fromstr 1.0000000000[rb]
# the next line does the same, but smarter
set y [lb]fromstr 1. 10[rb]
# the next line set a BigInt equal to 1
set n [lb]fromstr 1[rb]
# the next line raises an error : a single argument is required
# for strings to BigInts conversions
set n [lb]fromstr 1 10[rb]
# the next line is correct
set n [lb]fromstr 1[lb]string repeat 0 10[rb][rb]
[example_end]


[call [cmd tostr] [arg number]]
Returns a string form of a BigFloat, in which all digits are exacts,
or the string form of a BigInt if [emph number] is not a BigFloat.
There is an issue with number equal to zero
(see section [sectref PRECISION]) : even if the precision about 0 is
more than one digit, it will always be displayed as the '[emph 0]' string.

[call [cmd fromdouble] [arg double] [opt [arg decimals]]]

Converts a double (a simple floating-point value) to a BigFloat, with
exactly [arg decimals] digits.  Without the [arg decimals] argument,
it behaves like [emph fromstr].

[example_begin]
tostr [lb]fromstr 1.111 4[rb]
# returns : 1.111000 (3 zeroes)
tostr [lb]fromdouble 1.111 4[rb]
# returns : 1.111
[example_end]

[call [cmd todouble] [arg number]]
Returns a double, that may be used in [emph expr],
from a BigFloat.

[call [cmd isInt] [arg number]]
Returns 1 if [emph number] is a BigInt, 0 otherwise.

[call [cmd isFloat] [arg number]]
Returns 1 if [emph number] is a BigFloat, 0 otherwise.

[call [cmd int2float] [arg integer] [opt [arg decimals]]]
Converts a BigInt to a BigFloat with [emph decimals] trailing zeroes.
When converting back to string, one decimal is lost.
That is why the default, and minimal, number of [emph decimals] is 1.


[list_end]

[section "ARITHMETICS"]
[list_begin definitions]

[call [cmd add] [arg x] [arg y]]
[call [cmd sub] [arg x] [arg y]]
[call [cmd mul] [arg x] [arg y]]
Return the sum, difference and product of [emph x] by [emph y].
[arg x] - may be either a BigFloat or a BigInt
[arg y] - may be either a BigFloat or a BigInt

[call [cmd div] [arg x] [arg y]]
[call [cmd mod] [arg x] [arg y]]
Return the quotient and the rest of [emph x] divided by [emph y].
Each argument ([emph x] and [emph y]) can be either a BigFloat or a BigInt,
but you cannot divide a BigInt by a BigFloat
Divide by zero throws an error.

[call [cmd abs] [arg x]]
Returns the absolute value of [emph x]

[call [cmd opp] [arg x]]
Returns the opposite of [emph x]

[call [cmd pow] [arg x] [arg n]]
Returns [emph x] taken to the [emph n]th power.
It only works if [emph n] is a BigInt.
[emph x] might be a BigFloat or a BigInt.


[list_end]

[section COMPARISONS]
[list_begin definitions]
[call [cmd iszero] [arg x]]

Returns 1 if [emph x] is :
[list_begin bullet]
[bullet]a BigFloat close enough to zero to raise "divide by zero".
[bullet]a BigInt equal to 0.
[list_end]
[call  [cmd equal] [arg x] [arg y]]

Returns 1 if [emph x] and [emph y] are equal, 0 elsewhere.

[call [cmd compare] [arg x] [arg y]]

Returns 0 if both BigFloat arguments are equal,
1 if [emph x] is greater than [emph y],
and -1 if [emph x] is lower than [emph y].
You might compare two BigFloats or two BigInts, but not a BigInt to a BigFloat.

[list_end]

[section ANALYSIS]
[list_begin definitions]
[call [cmd sqrt] [arg x]]
[call [cmd log] [arg x]]
[call [cmd exp] [arg x]]
[call [cmd cos] [arg x]]
[call [cmd sin] [arg x]]
[call [cmd tan] [arg x]]
[call [cmd cotan] [arg x]]
[call [cmd acos] [arg x]]
[call [cmd asin] [arg x]]
[call [cmd atan] [arg x]]
[call [cmd cosh] [arg x]]
[call [cmd sinh] [arg x]]
[call [cmd tanh] [arg x]]

The above functions return, respectively, the following :
square root, logarithm, exponential, cosine, sine,
tangent, cotangent, arc cosine, arc sine, arc tangent, hyperbolic
cosine, hyperbolic sine, hyperbolic tangent, of a BigFloat named [emph x].

[call [cmd pi] [arg n]]
Returns a BigFloat representing the Pi constant with [emph n] digits after the dot.
[emph n] may be either a simple string, or a BigInt.

[call [cmd rad2deg] [arg radians]]
[call [cmd deg2rad] [arg degrees]]
[arg radians] - angle expressed in radians (BigFloat)
[nl]
[arg degrees] - angle expressed in degrees (BigFloat)
[nl]
Convert an angle from radians to degrees, and [emph "vice versa"].

[list_end]

[section ROUNDING]
[list_begin definitions]
[call [cmd round] [arg x]]
[call [cmd ceil] [arg x]]
[call [cmd floor] [arg x]]

The above functions return the [emph x] BigFloat,
rounded like with the same mathematical function in [emph expr],
but returns a BigInt.

[list_end]
[section PRECISION]
Now you may ask this question : What precision am I going to get
after calling add, sub, mul or div?
When you set a number from the string representation, say
[example_begin]
set a [lb]fromstr 1.230[rb]
# $a is internally 1.230 +/- d.10^-3
# 'd' is a number in the [lb]1,2[lb] range
set a [lb]fromstr 1.000[rb]
# 'a' has a relative uncertainty in the range : [rb]0.1%,0.2%[rb]
# because 1*10^-3/1.000=0.1%, and 2*10^-3/1.000=0.2%
[example_end]
The uncertainty of the sum, or the difference, of two numbers, is the sum of the uncertainty
of each number.
[example_begin]
set a [lb]fromstr 1.230[rb]
set b [lb]fromstr 2.340[rb]
puts [lb]tostr [lb]add $a $b[rb][rb]
# the result is : 3.57 and the last digit of the sum is known with an uncertainty in the
# range [lb]2*10^-3,4*10^-3[lb]
[example_end]
But when operating a BigInt to a BigFloat (add, substract,etc.), the relative uncertainty
of the result is unchanged. So it is likely to keep integers as BigInt and not to
convert them to BigFloats.
[para]
For multiplication and division, the relative uncertainties of the product
or the quotient, is the sum of the relative uncertainties of the operands.
[para]
Take care about the fact that if a number contains 0 in its uncertainty interval,
it is always considered as if it was 0.
[example_begin]
set num [lb]fromstr 4.00[rb]
set denom [lb]fromstr 0.1[rb];# $denom is 0, because [lb]0.0,0.2[rb] contains 0
puts [lb]tostr $denom[rb];# prints "0" on the screen
set quotient [lb]div $num $denom[rb];# throws an error : divide by zero
set oppn [lb]opp $num[rb]
set oppd [lb]opp $denom[rb]
puts [lb]compare $num $oppn[rb];#prints 1
puts [lb]compare $denom $oppd[rb];#prints 0 !
[example_end]
[para]
For most analysis functions (cosinus, square root, logarithm, etc.), determining the precision
of the result is difficult.
It seems however that in many cases, the loss of precision in the result
is of one or two digits.
There are some exceptions : for example,
[example_begin]
tostr [lb]exp [lb]fromstr 100.0 10[rb][rb]
# returns : 2.688117142e+43 which has only 10 digits of precision, although the entry
# has 13 digits of precision.
[example_end]
[para]

How do conversions work with precision ?
[list_begin bullet]
[bullet] When a number is converted from string, the internal representation keep the uncertainty
as 1 to the exponent of the last digit.
[bullet] During computations, the uncertainty of each result is kept on two digits, eventually shifted and rounded when it is more than two digits long.
[bullet] When converting back to string, the digits that are printed are all digits except the two last digits,
because the last digits are subject to uncertainty.
[list_end]
Uncertainties are kept in the internal representation of the number ; it is likely to use
[emph tostr] only for outputting data (on the screen or in a file),
and never call [emph fromstr] with the result of [emph tostr].
It is better to always keep operands in their internal representation.

[section "NAMESPACES AND OTHER PACKAGES"]
You might import public commands with the following :
[example_begin]
namespace import ::math::bigfloat::*
[example_end]
If you matter much about avoiding names conflicts, I considere it should be resolved by the following :
[example_begin]
# the math::bignum package is required by the following statement
package require math::bigfloat
proc bigfloat {subcmd args} {
    uplevel 1 [lb]concat ::math::bigfloat::$subcmd $args[rb]
}
set a [lb]bigfloat sub [lb]bigfloat fromstr 2.000[rb] [lb]bigfloat fromstr 0.530[rb][rb]
puts [lb]bigfloat tostr $a[rb]
[example_end]
[section "EXAMPLES"]
Guess what happens when you are doing some astronomy. Here is an example :
[example_begin]
# convert acurrate angles with a millisecond-rated accuracy
proc degree-angle {degrees minutes seconds milliseconds} {
    set result [lb]fromstr 0[rb]
    set div [lb]fromstr 1[rb]
    foreach factor {1 1000 60 60} var [lb]list $milliseconds $seconds $minutes $degrees[rb] {
        # we convert each entry var into milliseconds
        set factor [lb]fromstr $factor[rb]
        set div [lb]mul $div $factor[rb]
        set result [lb]add $result [lb]mul [lb]fromstr $var[rb] $div[rb][rb]
    }
    return [lb]div [lb]int2float $result[rb] $div[rb]
}
# load the package
package require math::bigfloat
namespace import ::math::bigfloat::*
# work with angles : a standard formula for navigation (taking bearings)
set angle1 [lb]deg2rad [lb]degree-angle 20 30 40   0[rb][rb]
set angle2 [lb]deg2rad [lb]degree-angle 21  0 50 500[rb][rb]
set opposite3 [lb]deg2rad [lb]degree-angle 51  0 50 500[rb][rb]
set sinProduct [lb]mul [lb]sin $angle1[rb] [lb]sin $angle2[rb][rb]
set cosProduct [lb]mul [lb]cos $angle1[rb] [lb]cos $angle2[rb][rb]
set angle3 [lb]asin [lb]add [lb]mul $sinProduct [lb]cos $opposite3[rb][rb] $cosProduct[rb][rb]
puts "angle3 : [lb]tostr [lb]rad2deg $angle3[rb][rb]"
[example_end]
[keywords tcl multiprecision math floating-point]

[manpage_end]