# Numeric is the class from which all higher-level numeric classes should # inherit. # # Numeric allows instantiation of heap-allocated objects. Other core numeric # classes such as Integer are implemented as immediates, which means that each # Integer is a single immutable object which is always passed by value. # # a = 1 # 1.object_id == a.object_id #=> true # # There can only ever be one instance of the integer `1`, for example. Ruby # ensures this by preventing instantiation. If duplication is attempted, the # same instance is returned. # # Integer.new(1) #=> NoMethodError: undefined method `new' for Integer:Class # 1.dup #=> 1 # 1.object_id == 1.dup.object_id #=> true # # For this reason, Numeric should be used when defining other numeric classes. # # Classes which inherit from Numeric must implement `coerce`, which returns a # two-member Array containing an object that has been coerced into an instance # of the new class and `self` (see #coerce). # # Inheriting classes should also implement arithmetic operator methods (`+`, # `-`, `*` and `/`) and the `<=>` operator (see Comparable). These methods may # rely on `coerce` to ensure interoperability with instances of other numeric # classes. # # class Tally < Numeric # def initialize(string) # @string = string # end # # def to_s # @string # end # # def to_i # @string.size # end # # def coerce(other) # [self.class.new('|' * other.to_i), self] # end # # def <=>(other) # to_i <=> other.to_i # end # # def +(other) # self.class.new('|' * (to_i + other.to_i)) # end # # def -(other) # self.class.new('|' * (to_i - other.to_i)) # end # # def *(other) # self.class.new('|' * (to_i * other.to_i)) # end # # def /(other) # self.class.new('|' * (to_i / other.to_i)) # end # end # # tally = Tally.new('||') # puts tally * 2 #=> "||||" # puts tally > 1 #=> true # class Numeric include Comparable public # `x.modulo(y)` means `x-y*(x/y).floor`. # # Equivalent to `num.divmod(numeric)[1]`. # # See Numeric#divmod. # def %: (Numeric) -> Numeric # Unary Plus---Returns the receiver. # def +@: () -> Numeric # Unary Minus---Returns the receiver, negated. # def -@: () -> Numeric # Returns zero if `number` equals `other`, otherwise returns `nil`. # def <=>: (Numeric other) -> Integer # Returns the absolute value of `num`. # # 12.abs #=> 12 # (-34.56).abs #=> 34.56 # -34.56.abs #=> 34.56 # # Numeric#magnitude is an alias for Numeric#abs. # def abs: () -> Numeric # Returns square of self. # def abs2: () -> Numeric # Returns 0 if the value is positive, pi otherwise. # def angle: () -> Numeric # Returns 0 if the value is positive, pi otherwise. # alias arg angle # Returns the smallest number greater than or equal to `num` with a precision of # `ndigits` decimal digits (default: 0). # # Numeric implements this by converting its value to a Float and invoking # Float#ceil. # def ceil: () -> Integer | (Integer digits) -> (Integer | Numeric) # If `numeric` is the same type as `num`, returns an array `[numeric, num]`. # Otherwise, returns an array with both `numeric` and `num` represented as Float # objects. # # This coercion mechanism is used by Ruby to handle mixed-type numeric # operations: it is intended to find a compatible common type between the two # operands of the operator. # # 1.coerce(2.5) #=> [2.5, 1.0] # 1.2.coerce(3) #=> [3.0, 1.2] # 1.coerce(2) #=> [2, 1] # def coerce: (Numeric) -> [ Numeric, Numeric ] # Returns self. # def conj: () -> Numeric # Returns self. # def conjugate: () -> Numeric # Returns the denominator (always positive). # def denominator: () -> Integer # Uses `/` to perform division, then converts the result to an integer. Numeric # does not define the `/` operator; this is left to subclasses. # # Equivalent to `num.divmod(numeric)[0]`. # # See Numeric#divmod. # def div: (Numeric) -> Integer # Returns an array containing the quotient and modulus obtained by dividing # `num` by `numeric`. # # If `q, r = x.divmod(y)`, then # # q = floor(x/y) # x = q*y + r # # The quotient is rounded toward negative infinity, as shown in the following # table: # # a | b | a.divmod(b) | a/b | a.modulo(b) | a.remainder(b) # ------+-----+---------------+---------+-------------+--------------- # 13 | 4 | 3, 1 | 3 | 1 | 1 # ------+-----+---------------+---------+-------------+--------------- # 13 | -4 | -4, -3 | -4 | -3 | 1 # ------+-----+---------------+---------+-------------+--------------- # -13 | 4 | -4, 3 | -4 | 3 | -1 # ------+-----+---------------+---------+-------------+--------------- # -13 | -4 | 3, -1 | 3 | -1 | -1 # ------+-----+---------------+---------+-------------+--------------- # 11.5 | 4 | 2, 3.5 | 2.875 | 3.5 | 3.5 # ------+-----+---------------+---------+-------------+--------------- # 11.5 | -4 | -3, -0.5 | -2.875 | -0.5 | 3.5 # ------+-----+---------------+---------+-------------+--------------- # -11.5 | 4 | -3, 0.5 | -2.875 | 0.5 | -3.5 # ------+-----+---------------+---------+-------------+--------------- # -11.5 | -4 | 2, -3.5 | 2.875 | -3.5 | -3.5 # # Examples # # 11.divmod(3) #=> [3, 2] # 11.divmod(-3) #=> [-4, -1] # 11.divmod(3.5) #=> [3, 0.5] # (-11).divmod(3.5) #=> [-4, 3.0] # 11.5.divmod(3.5) #=> [3, 1.0] # def divmod: (Numeric) -> [ Numeric, Numeric ] # Returns `true` if `num` and `numeric` are the same type and have equal values. # Contrast this with Numeric#==, which performs type conversions. # # 1 == 1.0 #=> true # 1.eql?(1.0) #=> false # 1.0.eql?(1.0) #=> true # def eql?: (untyped) -> bool # Returns float division. # def fdiv: (Numeric) -> Numeric # Returns `true` if `num` is a finite number, otherwise returns `false`. # def finite?: () -> bool # Returns the largest number less than or equal to `num` with a precision of # `ndigits` decimal digits (default: 0). # # Numeric implements this by converting its value to a Float and invoking # Float#floor. # def floor: () -> Integer | (Integer digits) -> Numeric # Returns the corresponding imaginary number. Not available for complex numbers. # # -42.i #=> (0-42i) # 2.0.i #=> (0+2.0i) # def i: () -> Complex # Returns zero. # def imag: () -> Numeric # Returns zero. # def imaginary: () -> Numeric # Returns `nil`, -1, or 1 depending on whether the value is finite, `-Infinity`, # or `+Infinity`. # def infinite?: () -> Integer? # Returns `true` if `num` is an Integer. # # 1.0.integer? #=> false # 1.integer? #=> true # def integer?: () -> bool # Returns the absolute value of `num`. # # 12.abs #=> 12 # (-34.56).abs #=> 34.56 # -34.56.abs #=> 34.56 # # Numeric#magnitude is an alias for Numeric#abs. # alias magnitude abs # `x.modulo(y)` means `x-y*(x/y).floor`. # # Equivalent to `num.divmod(numeric)[1]`. # # See Numeric#divmod. # def modulo: (Numeric) -> Numeric # Returns `true` if `num` is less than 0. # def negative?: () -> bool # Returns `self` if `num` is not zero, `nil` otherwise. # # This behavior is useful when chaining comparisons: # # a = %w( z Bb bB bb BB a aA Aa AA A ) # b = a.sort {|a,b| (a.downcase <=> b.downcase).nonzero? || a <=> b } # b #=> ["A", "a", "AA", "Aa", "aA", "BB", "Bb", "bB", "bb", "z"] # def nonzero?: () -> self? # Returns the numerator. # def numerator: () -> Numeric # Returns 0 if the value is positive, pi otherwise. # alias phase angle # Returns an array; [num.abs, num.arg]. # def polar: () -> [ Numeric, Numeric ] # Returns `true` if `num` is greater than 0. # def positive?: () -> bool # Returns the most exact division (rational for integers, float for floats). # def quo: (Numeric) -> Numeric # Returns self. # def real: () -> Numeric # Returns `true` if `num` is a real number (i.e. not Complex). # def real?: () -> bool # Returns an array; [num, 0]. # def rect: () -> [ Numeric, Numeric ] # Returns an array; [num, 0]. # alias rectangular rect # `x.remainder(y)` means `x-y*(x/y).truncate`. # # See Numeric#divmod. # def remainder: (Numeric) -> Numeric # Returns `num` rounded to the nearest value with a precision of `ndigits` # decimal digits (default: 0). # # Numeric implements this by converting its value to a Float and invoking # Float#round. # def round: () -> Integer | (Integer digits) -> Numeric # Invokes the given block with the sequence of numbers starting at `num`, # incremented by `step` (defaulted to `1`) on each call. # # The loop finishes when the value to be passed to the block is greater than # `limit` (if `step` is positive) or less than `limit` (if `step` is negative), # where `limit` is defaulted to infinity. # # In the recommended keyword argument style, either or both of `step` and # `limit` (default infinity) can be omitted. In the fixed position argument # style, zero as a step (i.e. `num.step(limit, 0)`) is not allowed for # historical compatibility reasons. # # If all the arguments are integers, the loop operates using an integer counter. # # If any of the arguments are floating point numbers, all are converted to # floats, and the loop is executed *floor(n + n*Float::EPSILON) + 1* times, # where *n = (limit - num)/step*. # # Otherwise, the loop starts at `num`, uses either the less-than (`<`) or # greater-than (`>`) operator to compare the counter against `limit`, and # increments itself using the `+` operator. # # If no block is given, an Enumerator is returned instead. Especially, the # enumerator is an Enumerator::ArithmeticSequence if both `limit` and `step` are # kind of Numeric or `nil`. # # For example: # # p 1.step.take(4) # p 10.step(by: -1).take(4) # 3.step(to: 5) {|i| print i, " " } # 1.step(10, 2) {|i| print i, " " } # Math::E.step(to: Math::PI, by: 0.2) {|f| print f, " " } # # Will produce: # # [1, 2, 3, 4] # [10, 9, 8, 7] # 3 4 5 # 1 3 5 7 9 # 2.718281828459045 2.9182818284590453 3.118281828459045 # def step: (?Numeric limit, ?Numeric step) { (Numeric) -> void } -> self | (?Numeric limit, ?Numeric step) -> Enumerator[Numeric, self] | (?by: Numeric, ?to: Numeric) { (Numeric) -> void } -> self | (?by: Numeric, ?to: Numeric) -> Enumerator[Numeric, self] # Returns the value as a complex. # def to_c: () -> Complex # Invokes the child class's `to_i` method to convert `num` to an integer. # # 1.0.class #=> Float # 1.0.to_int.class #=> Integer # 1.0.to_i.class #=> Integer # def to_int: () -> Integer # Returns `num` truncated (toward zero) to a precision of `ndigits` decimal # digits (default: 0). # # Numeric implements this by converting its value to a Float and invoking # Float#truncate. # def truncate: () -> Integer | (Integer ndigits) -> (Integer | Numeric) # Returns `true` if `num` has a zero value. # def zero?: () -> bool end