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

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?

Returns:

  • (Boolean)


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