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