Module: Flt
- Defined in:
- lib/flt/complex.rb,
lib/flt/num.rb,
lib/flt/math.rb,
lib/flt/bin_num.rb,
lib/flt/dec_num.rb,
lib/flt/support.rb,
lib/flt/version.rb,
lib/flt/tolerance.rb,
lib/flt/trigonometry.rb,
lib/flt/support/reader.rb,
lib/flt/tolerance/sugar.rb,
lib/flt/support/formatter.rb,
lib/flt/support/flag_values.rb,
lib/flt/support/rationalizer.rb,
lib/flt/support/rationalizer_extra.rb
Overview
Tolerance for floating-point types (Float, Flt::BinNum, Flt::DecNum)
Tolerance can be used to allow for a tolerance in floating-point comparisons.
A Tolerance can be defined independently of the type (floating-point numeric class) it will be used with; The actual tolerance value will be compute for a particular reference value, and for some kinds of tolerance (e.g. epsilon) a value is not available without a reference:
tol = Tolerance(3, :decimals)
puts tol.value(DecNum('10.0')).inspect # -> DecNum('0.0005')
puts tol.value(10.0).inspect # -> 0.0005
puts tol.value.inspect # -> Rational(1, 2000)
tol = Tolerance(:epsilon)
puts tol.value(DecNum('10.0')).inspect # -> DecNum('1.00E-26')
puts tol.value(10.0).inspect # -> 2.22044604925031e-15
puts tol.value.inspect # -> nil
Tolerances can be:
-
Absolute: the tolerance value is a fixed value independent of the values to be compared.
-
Relative: the tolerance value is adjusted (scaled) to the magnitude of the numbers to be compared, so that it specifies admisible relative error values. Particular cases of relative tolerance are Percent and Permille tolerance.
-
Floating: tolerance is scaled along with the floating-point values. Floating tolerances can be :native (the scaling is done with the same base as the floating point radix), or have a specific base. Currently floating tolerances use the :low convention at the powers of the radix (as ulps). Floating tolerances should be computed at the correct or exact value to be compared, not at an approximation, but note that binary tolerance operations (equals?, less_than?, …) consider both arguments as approximations. A special case of a floating tolerance are tolerances specified in ULPs.
Tolerances can be specified as:
-
A specific value (valid for any type of tolerance: absolute, relative & floating)
-
A number of digits, or, for specific bases, decimals or bits, available for absolute and floating (significant).
-
Epsilon (or Big epsilon), optionally multiplied by a factor, available for all types of tolerances
-
A number of ULPs, which implies a floating tolerance.
-
A percent or permille value, only for relative tolerances.
There exists a Tolerance-derived class for each valid combination of type of tolerance and specification mode, but they all can be defined with the Tolerance() constructor. The first parameter to the constructor is the tolerance value, and in some kinds of tolerance it can be omitted. Next, the kind of tolerance is passed as a symbol; valid values are:
-
:absolute
-
:relative
-
:floating Generic floating decimal; another parameter can be passed for a specific base
-
:percent a particular kind of relative tolerance
-
:permille a particular kind of relative tolerance
-
:ulps a particular kind of floating tolerance
-
:sig_decimals (significative rounded decimals) a particular kind of floating tolerance; another parameter specifies if rounded
-
:decimals a particular kind of absolute tolerance
-
:sig_bits (significative bits) a particular kind of floating tolerance; another parameter specifies if rouded
-
:epsilon relative tolerance given as a multiple of epsilon (1 by default)
-
:abs_epsilon absolute tolerance given as a multiple of epsilon (1 by default)
-
:flt_epsilon floating tolerance given as a multiple of epsilon (1 by default)
-
:big_epsilon relative tolerance given as a multiple of big-epsilon (1 by default)
-
:abs_big_epsilon absolute tolerance given as a multiple of big-epsilon (1 by default)
-
:flt_big_epsilon floating tolerance given as a multiple of big-epsilon (1 by default)
Examples:
tol = Tolerance(100, :absolute)
puts tol.value(1.0) # -> 100.0
puts tol.value(1.5) # -> 100.0
puts tol.value(1.0E10) # -> 100.0
puts tol.eq?(11234.0, 11280.0) # -> true
tol = Tolerance(100, :relative)
puts tol.value(1.0) # -> 100.0
puts tol.value(1.5) # -> 150.0
puts tol.value(1.0E10) # -> 1000000000000.0
puts tol.eq?(11234.0, 11280.0) # -> true
tol = Tolerance(100, :floating)
puts tol.value(1.0) # -> 100.0
puts tol.value(1.5) # -> 200.0
puts tol.value(1.0E10) # -> 1717986918400.0
puts tol.eq?(11234.0, 11280.0) # -> true
tol = Tolerance(3, :sig_decimals)
puts tol.eq?(1.234,1.23) # -> true
tol = Tolerance(1, :ulps)
puts tol.eq?(3.3433, 3.3433.next_plus) # -> true
puts tol.eq?(DecNum('1.1'), DecNum('1.1').next_plus) # -> true
tol = Tolerance(1, :percent)
puts tol.equal_to?(3.14159, Math::PI) # -> true#
Defined Under Namespace
Modules: BigEpsilonMixin, EpsilonMixin, MathBase, Support, Trigonometry Classes: AbsBigEpsilonTolerance, AbsEpsilonTolerance, AbsoluteTolerance, BigDecimalContext, BigEpsilonTolerance, BinNum, ComplexContext, DecNum, DecimalsTolerance, EpsilonTolerance, FloatContext, FloatingTolerance, FltBigEpsilonTolerance, FltEpsilonTolerance, Num, PercentTolerance, PermilleTolerance, RelativeTolerance, SigBitsTolerance, SigDecimalsTolerance, Tolerance, UlpsTolerance
Constant Summary collapse
- VERSION =
"1.5.4"
Class Method Summary collapse
- .BinNum(*args) ⇒ Object
- .ComplexContext(context) ⇒ Object
-
.DecNum(*args) ⇒ Object
If a DecNum is passed a reference to it is returned (no new object is created).
-
.float_correctly_rounded? ⇒ Boolean
Is Float('…') correctly rounded, even for subnormal numbers?.
-
.Tolerance(*args) ⇒ Object
Tolerance constructor.
Class Method Details
.BinNum(*args) ⇒ Object
251 252 253 |
# File 'lib/flt/bin_num.rb', line 251 def BinNum(*args) BinNum.Num(*args) end |
.ComplexContext(context) ⇒ Object
295 296 297 |
# File 'lib/flt/complex.rb', line 295 def ComplexContext(context) ComplexContext.new(context) end |
.DecNum(*args) ⇒ Object
If a DecNum is passed a reference to it is returned (no new object is created).
1214 1215 1216 |
# File 'lib/flt/dec_num.rb', line 1214 def DecNum(*args) DecNum.Num(*args) end |
.float_correctly_rounded? ⇒ Boolean
Is Float('…') correctly rounded, even for subnormal numbers?
528 529 530 531 |
# File 'lib/flt/float.rb', line 528 def Flt.float_correctly_rounded? # That doesn't seem to be the case for mswin32 @float_correctly_rounded ||= RUBY_PLATFORM.match(/mswin32/).nil? end |
.Tolerance(*args) ⇒ Object
Tolerance constructor.
The first parameter is the value (magnitude) of the tolerance, and is optional for some tolerances.
The next parameter is the kind of tolerance as a symbol. It corresponds to the name of the implementation class minus the Tolerance suffix, and converted to snake-case (lowercase with underscores to separate words.)
Finally any additional parameters admitted by the class constructor can be passed.
546 547 548 549 550 551 552 553 554 555 |
# File 'lib/flt/tolerance.rb', line 546 def Tolerance(*args) return args.first if args.size == 1 && Tolerance === args.first if args.first.is_a?(Symbol) value = nil else value = args.shift end cls_name = (args.shift || :absolute).to_s.gsub(/(^|_)(.)/){$2.upcase} + "Tolerance" Flt.const_get(cls_name).new(value, *args) end |