#---Number---
Ruby provides robust support for working with numbers.
It can help with your numeric needs whether you make big integer amounts of fiat money or discrete fractional representations of crypto money. It doesn’t judge you.
+-/*%p (11 + 2 - 3 * 4/5) % 6 # => 5
**p "5^3 is #{5**3}" # => "5^3 is 125"
Note: The carat symbol ^ is used in Mathematics for
exponentiation. But in Ruby we use it for bitwise XOR.
For exponentiation, use **.
p "bitwise 5^3 is #{5^3}"
## => "bitwise 5^3 is 6"
If you need accurate floating point arithmetic, you
should use the standard library’s BigDecimal instead
of Float.
p (4.3 - 4.1) == 0.2 # => false
require 'bigdecimal'
p (BigDecimal('4.3') - BigDecimal('4.1')) \
== BigDecimal('0.2') # true
With to_i and to_f methods, easily convert
between number types.
p 1/2 # => 0
p 1/(2.to_f) # => 0.5
But normally you don’t even have to do that. Ruby will infer the type based on the value.
p 84/2 # => 42 (Integer)
p 84.0/2 # => 42.0 (Float)
These are even available on strings!
p '3'.to_i # => 3
p '3.9'.to_i # => 3
p '3.9'.to_f # => 3.9
But be careful. Don’t trust these blindly.
p 'asdf3'.to_i # => 0
p '3asdf'.to_i # => 3
p '3.456asdf'.to_f # => 3.456
Use to_s to convert any numeric type to string.
p 1_000_000.to_s # => "1000000"
All number types are Numeric. And all numeric types
include the Comparable module which gives the objects
of these types the ability to compare. Comparison
methods this module gives are:
==<><=>=p 5 > 4.3 # => true
It also gives the between? and clamp methods which
are neat. Can be used to set min, max limits.
p 5.between?(2, 10) # => true
p 42.clamp(1, 100) # => 42
p 101.clamp(1, 100) # => 100
p 0.clamp(1, 100) # => 1
Besides the above three, there are other methods such as
abs, floor, ceil, round, divmod, next
pred etc. There’s even a gcd.
p -34.abs # => 34
p 34.93.floor # => 34
p 34.16.ceil # => 35
p 34.16.round # => 34
p 47.divmod(42) # => [1, 5]
p 100.next # => 101
p 100.pred # => 99
p 500.gcd(1000) # => 500
And also predicate methods like zero?,
nonzero?, positive?, negative?, integer?,
finite?, infinite?, odd?, even? etc.
p 0.zero? # => true
p 5.even? # => false
p 5.odd? # => true
p 5.positive? # => true
p -5.negative? # => true
p Float::INFINITY.finite? # => false
The constants Float::INFINITY and -Float::INFINITY
are used to represent the two ends of the extremes.
p 1_000_000 < Float::INFINITY # => true
p -Float::INFINITY < -1_000_000 # => true
p (1/0) rescue nil
## => 💥 blows up with: `ZeroDivisionError` error without
## `rescue nil`
p (1/0.0) # => Infinity
They’re also used in endless ranges.
p (1..4).count # => 4
p (1..).count # => Infinity
Numeric is the parent class from which all these other
number-related classes inherit from.
Integerp 1.class # => Integer
Floatp (3.14).class # => Float
Rationalp (1/3r).class # => Rational
Complexp (1 + 2i).class # => Complex
Let’s explore the object/class hierarchy of numbers a bit:
p 2.is_a?(Integer) # => true
p 2.is_a?(Numeric) # => true
p 2.is_a?(Comparable) # => true
p 2.is_a?(Float) # => false
p 3.14.class.ancestors
##=>[Float, JSON::Ext::Generator::GeneratorMethods::Float,
## Numeric, Comparable, Object,
## JSON::Ext::Generator::GeneratorMethods::Object,
## PP::ObjectMixin, Kernel, BasicObject]
Before Ruby 2.4, the integers were represented using
these 2 Integer sub-classes: Fixnum and Bignum.
But 2.4 got rid of them. Good riddance. Just use
Integer and Float now.
Since the number values are ruby objects, all the functionalities are available as methods on them instead of functions or operators like in most other languages.
The ability to call them without a dot and paranthesis is just a Ruby syntax sugar to make it seem elegant like operators.
That means 11 + 5 is actually 11.+(5). And
11 <= 12 is 11.<=(12):
p 11.+(5) # => 16
p 11.<=(12) # => true