Homepage > Man Pages > Category > Subroutines
Homepage > Man Pages > Name > M

# math::bigfloat

## man page of math::bigfloat

### math::bigfloat: Arbitrary precision floating-point numbers

```NAME
math::bigfloat - Arbitrary precision floating-point numbers

SYNOPSIS
package require Tcl  8.5

package require math::bigfloat  ?2.0.1?

fromstr number ?trailingZeros?

tostr ?-nosci? number

fromdouble double ?decimals?

todouble number

isInt number

isFloat number

int2float integer ?decimals?

sub x y

mul x y

div x y

mod x y

abs x

opp x

pow x n

iszero x

equal x y

compare x y

sqrt x

log x

exp x

cos x

sin x

tan x

cotan x

acos x

asin x

atan x

cosh x

sinh x

tanh x

pi n

round x

ceil x

floor x

_________________________________________________________________

DESCRIPTION
The  bigfloat  package provides arbitrary precision floating-point math
capabilities to the Tcl language. It is designed to work with Tcl  8.5,
but  for  Tcl  8.4 is provided an earlier version of this package.  See
WHAT ABOUT TCL 8.4 ? for more explanations.   By  convention,  we  will
talk about the numbers treated in this library as :

o      BigFloat for floating-point numbers of arbitrary length.

o      integers  for  arbitrary  length  signed integers, just as basic
integers since Tcl 8.5.

Each BigFloat is an  interval,  namely  [m-d,  m+d],  where  m  is  the
mantissa  and  d  the  uncertainty, representing the limitation of that
number's precision.  This is why  we  call  such  mathematics  interval
computations.   Just  take  an  example in physics : when you measure a
temperature, not all digits you read  are  significant.  Sometimes  you
just cannot trust all digits - not to mention if doubles (f.p. numbers)
can handle all these  digits.   BigFloat  can  handle  this  problem  -
trusting the digits you get - plus the ability to store numbers with an
arbitrary precision.   BigFloats  are  internally  represented  at  Tcl
lists:  this package provides a set of procedures operating against the
internal representation in order to :

o      perform math  operations  on  BigFloats  and  (optionnaly)  with
integers.

o      convert   BigFloats   from  their  internal  representations  to
strings, and vice versa.

INTRODUCTION
fromstr number ?trailingZeros?
Converts number into a BigFloat. Its precision is at  least  the
number  of  digits  provided  by number.  If the number contains
only digits and eventually a minus sign, it is considered as  an
integer. Subsequently, no conversion is done at all.

trailingZeros  - the number of zeros to append at the end of the
floating-point number  to  get  more  precision.  It  cannot  be
applied to an integer.

# x and y are BigFloats : the first string contained a dot, and the second an e sign
set x [fromstr -1.000000]
set y [fromstr 2000e30]
# let's see how we get integers
set t 20000000000000
# the old way (package 1.2) is still supported for backwards compatibility :
set m [fromstr 10000000000]
# but we do not need fromstr for integers anymore
set n -39
# t, m and n are integers

The  number's  last  digit is considered by the procedure to be true at
+/-1, For example, 1.00 is the interval  [0.99,  1.01],  and  0.43  the
interval  [0.42,  0.44].   The  Pi  constant may be approximated by the
number "3.1415".  This string  could  be  considered  as  the  interval
[3.1414  ,  3.1416] by fromstr.  So, when you mean 1.0 as a double, you
may have to write 1.000000 to get  enough  precision.   To  learn  more

For example :

set x [fromstr 1.0000000000]
# the next line does the same, but smarter
set y [fromstr 1. 10]

tostr ?-nosci? number
Returns  a  string  form  of a BigFloat, in which all digits are
exacts.  All exact  digits  means  a  rounding  may  occur,  for
example  to  zero,  if the uncertainty interval does not clearly
show the true digits.  number may be  an  integer,  causing  the
command  to  return exactly the input argument.  With the -nosci
option,  the  number  returned  is  never  shown  in  scientific
notation, i.e. not like '3.4523e+5' but like '345230.'.

puts [tostr [fromstr 0.99999]] ;# 1.0000
puts [tostr [fromstr 1.00001]] ;# 1.0000
puts [tostr [fromstr 0.002]] ;# 0.e-2

See  PRECISION  for  that  matter.   See  also iszero for how to detect
zeros, which is useful when performing a division.

fromdouble double ?decimals?
Converts a double (a simple floating-point value) to a BigFloat,
with exactly decimals digits.  Without the decimals argument, it
behaves like fromstr.  Here,  the  only  important  feature  you
might  care  of  is the ability to create BigFloats with a fixed
number of decimals.

tostr [fromstr 1.111 4]
# returns : 1.111000 (3 zeros)
tostr [fromdouble 1.111 4]
# returns : 1.111

todouble number
Returns a double, that may be used in expr, from a BigFloat.

isInt number
Returns 1 if number is an integer, 0 otherwise.

isFloat number
Returns 1 if number is a BigFloat, 0 otherwise.

int2float integer ?decimals?
Converts an integer to a BigFloat with decimals trailing  zeros.
The  default,  and  minimal,  number  of  decimals  is  1.  When
converting back to string, one decimal is lost:

set n 10
set x [int2float \$n]; # like fromstr 10.0
puts [tostr \$x]; # prints "10."
set x [int2float \$n 3]; # like fromstr 10.000
puts [tostr \$x]; # prints "10.00"

ARITHMETICS

sub x y

mul x y
Return the sum, difference and product of x by y.  x  -  may  be
either  a BigFloat or an integer y - may be either a BigFloat or
an integer When both are integers, these  commands  behave  like
expr.

div x y

mod x y
Return  the  quotient  and  the  rest  of  x divided by y.  Each
argument (x and y) can be either a BigFloat or an  integer,  but
you cannot divide an integer by a BigFloat Divide by zero throws
an error.

abs x  Returns the absolute value of x

opp x  Returns the opposite of x

pow x n
Returns x taken to the nth power.  It only  works  if  n  is  an
integer.  x might be a BigFloat or an integer.

COMPARISONS
iszero x
Returns 1 if x is :

o      a  BigFloat  close  enough  to  zero  to raise "divide by
zero".

o      the integer 0.
See here how numbers that are close to zero are converted to strings:

tostr [fromstr 0.001] ; # -> 0.e-2
tostr [fromstr 0.000000] ; # -> 0.e-5
tostr [fromstr -0.000001] ; # -> 0.e-5
tostr [fromstr 0.0] ; # -> 0.
tostr [fromstr 0.002] ; # -> 0.e-2

set a [fromstr 0.002] ; # uncertainty interval : 0.001, 0.003
tostr  \$a ; # 0.e-2
iszero \$a ; # false

set a [fromstr 0.001] ; # uncertainty interval : 0.000, 0.002
tostr  \$a ; # 0.e-2
iszero \$a ; # true

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

compare x y
Returns 0 if both BigFloat  arguments  are  equal,  1  if  x  is
greater  than  y, and -1 if x is lower than y.  You would not be
able to compare an integer to a BigFloat : the  operands  should
be both BigFloats, or both integers.

ANALYSIS
sqrt x

log x

exp x

cos x

sin x

tan x

cotan x

acos x

asin x

atan x

cosh x

sinh x

tanh 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 x.

pi n   Returns a BigFloat representing the Pi constant  with  n  digits
after the dot.  n is a positive integer.

degrees - angle expressed in degrees (BigFloat)

Convert an angle from radians to degrees, and vice versa.

ROUNDING
round x

ceil x

floor x
The above functions return the x BigFloat, rounded like with the
same mathematical  function  in  expr,  and  returns  it  as  an
integer.

PRECISION
How do conversions work with precision ?

o      When   a   BigFloat  is  converted  from  string,  the  internal
representation holds its uncertainty as 1 at the  level  of  the
last digit.

o      During   computations,   the   uncertainty  of  each  result  is
internally computed the closest to the reality, thus saving  the
memory used.

o      When  converting back to string, the digits that are printed are
not subject to uncertainty. However, some rounding is  done,  as
not doing so causes severe problems.

Uncertainties  are  kept in the internal representation of the number ;
it is recommended to use tostr only for outputting data (on the  screen
or  in a file), and NEVER call fromstr with the result of tostr.  It is
better to always keep operands in their internal  representation.   Due
to  the  internals  of  this  library,  the uncertainty interval may be
slightly wider than expected, but this should not cause false digits.

Now you may ask this question : What precision am I going to get  after
calling  add,  sub, mul or div?  First you set a number from the string
representation and, by the way, its uncertainty is set:

set a [fromstr 1.230]
# \$a belongs to [1.229, 1.231]
set a [fromstr 1.000]
# \$a belongs to [0.999, 1.001]
# \$a has a relative uncertainty of 0.1% : 0.001(the uncertainty)/1.000(the medium value)

The uncertainty of the sum, or the difference, of two numbers,  is  the
sum of their respective uncertainties.

set a [fromstr 1.230]
set b [fromstr 2.340]
# the result is : [3.568, 3.572] (the last digit is known with an uncertainty of 2)
tostr \$sum ; # 3.57

But  when,  for  example, we add or substract an integer to a BigFloat,
the relative uncertainty of the result is unchanged. So it is desirable
not to convert integers to BigFloats:

set a [fromstr 0.999999999]
# now something dangerous
set b [fromstr 2.000]
# the result has only 3 digits

# how to keep precision at its maximum

For  multiplication  and  division,  the  relative uncertainties of the
product or the quotient, is the sum of the  relative  uncertainties  of
the  operands.  Take care of division by zero : check each divider with
iszero.

set num [fromstr 4.00]
set denom [fromstr 0.01]

puts [iszero \$denom];# true
set quotient [div \$num \$denom];# error : divide by zero

# opposites of our operands
puts [compare \$num [opp \$num]]; # 1
puts [compare \$denom [opp \$denom]]; # 0 !!!
# No suprise ! 0 and its opposite are the same...

Effects of the precision of a number considered equal to  zero  to  the
cos function:

puts [tostr [cos [fromstr 0. 10]]]; # -> 1.000000000
puts [tostr [cos [fromstr 0. 5]]]; # -> 1.0000
puts [tostr [cos [fromstr 0e-10]]]; # -> 1.000000000
puts [tostr [cos [fromstr 1e-10]]]; # -> 1.000000000

BigFloats  with  different internal representations may be converted to
the same string.

For most analysis functions (cosine,  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,

tostr [exp [fromstr 100.0 10]]
# returns : 2.688117142e+43 which has only 10 digits of precision, although the entry
# has 14 digits of precision.

If  your setup do not provide Tcl 8.5 but supports 8.4, the package can
still be loaded, switching  back  to  math::bigfloat  1.2.  Indeed,  an
important  function  introduced in Tcl 8.5 is required - the ability to
handle bignums, that we can do with expr.  Before 8.5, this ability was
provided  by  several  packages,  including  the  pure-Tcl math::bignum
package provided by tcllib.  In this case, all you  need  to  know,  is
that  arguments  to  the commands explained here, are expected to be in
their internal representation.  So even with integers, you will need to
call  fromstr  and  tostr  in  order to convert them between string and
internal representations.

#
# with Tcl 8.5
# ============
set a [pi 20]
# round returns an integer and 'everything is a string' applies to integers
# whatever big they are
puts [round [mul \$a 10000000000]]
#
# the same with Tcl 8.4
# =====================
set a [pi 20]
# bignums (arbitrary length integers) need a conversion hook
set b [fromstr 10000000000]
# round returns a bignum:
# before printing it, we need to convert it with 'tostr'
puts [tostr [round [mul \$a \$b]]]

NAMESPACES AND OTHER PACKAGES
We have not yet discussed about namespaces because we assumed that  you
had imported public commands into the global namespace, like this:

namespace import ::math::bigfloat::*

If  you  matter  much  about  avoiding  names conflicts, I considere it
should be resolved by the following :

package require math::bigfloat
# beware: namespace ensembles are not available in Tcl 8.4
namespace eval ::math::bigfloat {namespace ensemble create -command ::bigfloat}
# from now, the bigfloat command takes as subcommands all original math::bigfloat::* commands
set a [bigfloat sub [bigfloat fromstr 2.000] [bigfloat fromstr 0.530]]
puts [bigfloat tostr \$a]

EXAMPLES
Guess what happens when you  are  doing  some  astronomy.  Here  is  an
example :

# convert acurrate angles with a millisecond-rated accuracy
proc degree-angle {degrees minutes seconds milliseconds} {
set result 0
set div 1
foreach factor {1 1000 60 60} var [list \$milliseconds \$seconds \$minutes \$degrees] {
# we convert each entry var into milliseconds
set div [expr {\$div*\$factor}]
incr result [expr {\$var*\$div}]
}
return [div [int2float \$result] \$div]
}
package require math::bigfloat
namespace import ::math::bigfloat::*
# work with angles : a standard formula for navigation (taking bearings)
set angle1 [deg2rad [degree-angle 20 30 40   0]]
set angle2 [deg2rad [degree-angle 21  0 50 500]]
set opposite3 [deg2rad [degree-angle 51  0 50 500]]
set sinProduct [mul [sin \$angle1] [sin \$angle2]]
set cosProduct [mul [cos \$angle1] [cos \$angle2]]
set angle3 [asin [add [mul \$sinProduct [cos \$opposite3]] \$cosProduct]]
puts "angle3 : [tostr [rad2deg \$angle3]]"

BUGS, IDEAS, FEEDBACK
This  document,  and the package it describes, will undoubtedly contain
bugs and other problems.  Please report such in the  category  math  ::
bignum      ::      float     of     the     Tcllib     SF     Trackers
any  ideas  for  enhancements  you  may  have for either package and/or
documentation.

KEYWORDS
computations, floating-point, interval, math, multiprecision, tcl

CATEGORY
Mathematics

Copyright (c) 2004-2008, by Stephane Arnold <stephanearnold at yahoo dot fr>

MATH::BIGFLOAT(3)
```