| Class | Float |
| In: |
float_ext.rb
|
| Parent: | Object |
Usage:
require 'float_ext.rb' x = 1.37; y = 0.123 phi = x.arg(y) r = x.hypot(y) dx = r * phi.cos - x dy = r * phi.sin - y
Defining all functons of module Math as methods of class Float. The meaning of functions frexp and ldexp has been changed from referring to exponent 2 to exponent 10. Notice that code that worked without a statement
require 'float_ext.rb'
will work in an identical manner with this statement added. Only if this is true, extending the functionaliy of standard types is considered acceptable. A few functions, not to be found in module Math have been added. These are methods which are defined in R and thus should be available in Float in order to make R and Float strictly replacable in all code that loads float_ext.rb and rnum.rb. These new functions are:
inv, pseudo_inv, conj, cot, coth, acot, acoth, arg, clone, dis, integer?, real?, complex?
Notice also, that for R.dig = -1, the real-number generating functions
R.ran, R.tob, R.c, R.i, R.pi, R.e R.c0, R.c1, ..., R.c10, R.i2, ... R.i10
that normally return R-numbers are forced to return Floats so that it is simple to write programs in such a manner that all real numbers switch their type from Float to R and vice versa. This is one mode more to use Float. Note that setting R.dig = 0 also uses Float, but does so in a hidden manner by basing the representation of R-numbers internally on Float. If an application has to switch between Float encoding of numbers and BigDecimal encoding of numbers one better uses R for all real numbers both and changes the representation by calling the function R.dig=. The class R is coded in a manner that it makes no use of the present extension of Float, although this would have allowed some code reduction.
The name ‘arg’ stands for ‘agument’, which is the name for the polar angle of a complex number preferred in the mahematical literature. So for a complex number z = u + iv we have
argument(z) = u.arg(v)
Notice also the representation of the absolute value of z:
|z| = u.hypot(v)
The functions hypot and arg (or atan2) thus prepare the introduction of complex numbers.
# File float_ext.rb, line 98
98: def arg(y); Math.atan2(y,self); end
One should have this!
# File float_ext.rb, line 145
145: def clone
146: res = 0.0; res += self; res
147: end
Not complex, since no second dimesion (filling a plane) is provided.
# File float_ext.rb, line 176
176: def complex?; false; end
(Complex) conjugation, no effect on real numbers. Supports the unified treatment of real and complex numbers.
# File float_ext.rb, line 69
69: def conj; self; end
All functions having ‘cot’ in their name deal with the trigonometric or hyperbolic cotangent. These functions are so directly related to the corresponding ‘tan’-functions that they are not included in the Math and BigMath modules. It is sometimes useful to have them, though.
# File float_ext.rb, line 106
106: def cot; Math.cos(self)/Math.sin(self); end
For all Float x, y we have 0 <= x.dis(y) <= 1 and x.dis(x) = 0 It is a kind of relative distance which should be in the order of magnitude of the smalles positive representable number if x and y are known to differ only by numerical noise.
# File float_ext.rb, line 153
153: def dis(x)
154: xf = x.to_f
155: a = abs
156: b = xf.abs
157: d = (self - xf).abs
158: s = a + b
159: return 0.0 if s.zero?
160: d1 = d/s
161: d < d1 ? d : d1
162: end
Warning! x.frexp differs from Math.frexp(x). We need exponent 10 not 2, so we don‘t use:
def frexp; Math.frexp(self);end
# File float_ext.rb, line 121
121: def frexp
122: # puts "arg of frex="+to_s
123: if zero?
124: [ 0.0, 0]
125: elsif self > 0.0
126: y = Math.log10(self)
127: yf = y.floor
128: yfrac = y - yf
129: [ 10.0 ** yfrac, yf.to_i]
130: else
131: y = Math.log10(-self)
132: yf = y.floor
133: yfrac = y - yf
134: [ - 10.0 ** yfrac, yf.to_i]
135: end
136: end
x.hypot(y) is an efficient and accurate representation of the square root of x*x + y*y.
# File float_ext.rb, line 58
58: def hypot(y); Math.hypot(self,y); end
Since Float is not Fixnum or Bignum we return ‘false’. In scientific computation there may be the need to use various types of ‘real number types’ but there should be always a clear-cut distinction between integer types and real types.
# File float_ext.rb, line 168
168: def integer?; false; end
It is convenient to have inversion (the multiplicative analogon of the unary - operation) as a member function.
# File float_ext.rb, line 62
62: def inv; 1.0/self; end
Warning! x.ldexp differs from Math.ldexp(x). We need exponent 10 not 2, so we don‘t use:
def ldexp(n); Math.ldexp(self,n);end
# File float_ext.rb, line 142
142: def ldexp(n); self * (10.0 ** n.to_i); end
Print. Output to console, together with a name which is given by the argument.
# File float_ext.rb, line 186
186: def prn(name)
187: puts " #{name} = " + to_s
188: end
pseudo inverse, which always exists
# File float_ext.rb, line 65
65: def pseudo_inv; zero? ? 0.0 : 1.0/self; end
Although there may be technical variants in representing real numbers, these all should answer this question with ‘yes’ since they all model mathematical real numbers.
# File float_ext.rb, line 173
173: def real?; true; end
Returns a real number, the significand of which has not more than n digits. Notice that there is also a function round which takes no argument and which returns an integer number. This function replaces function Float#round.
# File float_ext.rb, line 194
194: def round(*arg)
195: n = arg.size
196: case n
197: when 0
198: (self + 0.5).floor # output is integer
199: when 1
200: m = arg[0].to_i
201: x = frexp
202: y = x[0].ldexp(m)
203: (y + 0.5).floor.to_f.ldexp(x[1] - m)
204: else
205: fail "needs 0 or 1 arguments"
206: end
207: end