This gem originally provided two methods root
and roots
to find all the nth roots of real and complex values.
For details on their mathematical foundation and implementation details see my paper:
Roots in Ruby
https://www.scribd.com/doc/60067570/Roots-in-Ruby
In 2017 I added the methods iroot2
and iroot
|irootn
to find the integer roots for arbitrary sized integers.
Add this line to your application's Gemfile:
gem 'roots'
And then execute:
$ bundle
Or install it yourself as:
$ gem install roots
Then require as:
require 'roots'
Starting with Roots 2.0.0 (2017-2-21) the methods iroot2 and irootn were added (with iroot added as an alias to irootn 2017-6-1). With 2.1.0 iroot2 uses optimized Newton's method. With 2.2.0 (2017-6-17) iroot|n uses optimized Newton's method for any nth root. All are instance_methods of class Integer and accurately compute the exact real value square|nth roots for arbitrary sized integers.
If you have an application where you need the exact correct integer real value for roots, especially for arbitrary sized (large) integers, use these methods instead of root|s. These methods work strictly in the integer domain, and do not first create floating point approximations of these roots and then convert them to integers.
They are useful for applications in pure math, Number Theory, Cryptography, etc, where you need to find the exact real integer roots of polynomials, encryption functions, etc.
The methods root and roots work for all the Numeric classes (integers, floats, complex, rationals), and produce floating point results. They, thus, produce floating point approximations to the exact Integer values for real roots for arbitrary sized integers.
iroot2
Use syntax: ival.iroot2
Return the largest Integer +root+ of Integer ival such that root**2 <= ival
A negative ival will result in 'nil' being returned.
9.iroot2 => 3
-9.iroot2 => nil
120.iroot2 => 10
121.iroot2 => 11
121.iroot2.class => Integer
(10**10).iroot2 => 100000
(10**10).root(2) => 100000.0
(10**10).roots(2)[0] => 100000.0+0.0i
(10**11).iroot2 => 316227
(10**11).root(2) => 316227.76601684
(10**11).roots(2)[0] => 316227.76601684+0.0i
(10**110).iroot2 => 10000000000000000000000000000000000000000000000000000000
(10**110).root(2) => 1.0e+55
(10**110).roots(2)[0] => 1.0e+55+0.0i
(10**111).iroot2 => 31622776601683793319988935444327185337195551393252168268
(10**111).root(2) => 3.1622776601683795e+55
(10**111).roots(2)[0] => 3.1622776601683795e+55+0.0i
irootn or iroot
Use syntax: ival.irootn(n) or ival.iroot(n), where n is an Integer > 1
Return the largest Integer +root+ of Integer ival such that root**n <= ival
A negative ival for an even root n will result in 'nil' being returned.
81.irootn(2) => 9
81.irootn 3 => 4
81.iroot 4 => 3
81.iroot(4).class => Integer
-81.irootn(3) => -4
-81.irootn(4) => nil
100.irootn 4.5 => RuntimeError: root n is < 2 or not an Integer
100.iroot -2 => RuntimeError: root n is < 2 or not an Integer
(10**110).iroot(2) => 10000000000000000000000000000000000000000000000000000000
(10**110).irootn(3) => 4641588833612778892410076350919446576
(10**110).iroot 4 => 3162277660168379331998893544
(10**110).iroot(5) => 10000000000000000000000
(10**110).irootn(6) => 2154434690031883721
(10**110).irootn(7) => 5179474679231211
(10**110).irootn(8) => 56234132519034
(10**110).iroot(9) => 1668100537200
(10**110).iroot 10 => 100000000000
root
Use syntax: val.root(n,{k})
root(n,k=0) n is root 1/n exponent, integer > 0
k is nth ccw root 1..n , integer >=0
If k not given default root returned, which are:
for +val => real root |val**(1.0/n)|
for -val => real root -|val**(1.0/n)| when n is odd
for -val => first ccw complex root when n is even
9.root(2) => 3.0
-32.root(5,3) => (-2.0+0.0i)
73.root 6 => 2.04434322
73.root 6,1 => (2.04434322+0.0i)
(-100.43).root 6,6 => (1.86712994-1.07798797i)
Complex(3,19).root 7,4 => (-1.47939161+0.37266673i)
roots
Use syntax: val.roots(n,{opt})
roots(n,opt=0) n is root 1/n exponent, integer > 0
opt, optional string input, are:
0 : default (no input), return array of n ccw roots
'c'|'C': complex, return array of complex roots
'e'|'E': even, return array even numbered roots
'o'|'O': odd , return array odd numbered roots
'i'|'I': imag, return array of imaginary roots
'r'|'R': real, return array of real roots
An empty array is returned for an opt with no members.
9348134943.roots(9); -89.roots(4,'real'); 2.2.roots 3,'Im'
For Ruby >= 1.9 can also use a symbol as option: 384.roots 4,:r
Can ask: How many complex roots of x: x.roots(n,'c').size
What's the 3rd 5th root of (4+9i): Complex(4,9).root(5,3)
8.roots 3 => [(2.0+0.0i), (-1.0+1.73205081i), (-1.0-1.73205081i)]
Roots.digits_to_show
With version 1.1.0 this method was added to allow users to set
and see the number of decimal digits displayed. If no input is
given, the number of digits previously set is shown. The default
value is 8. Providing an input value sets the number of digits to
display. An input value < 1 will be set to a value of 1, to
display at least one decimal digit. An input greater than the
maximum digits shown for a given Ruby will display that maximum.
Roots.digits_to_show => 8
10.root 5 => 1.58489319
Roots.digits_to_show 11 => 11
10.root 5 => 1.58489319246
Roots.digits_to_show 16 => 16
10.root 5 => 1.5848931924611136
Roots.digits_to_show 17 => 17
10.root 5 => 1.5848931924611136
Roots.digits_to_show 0 => 1
10.root 5 => 1.6
For complex number (x+iy) = a*e^(i*arg) = a*[cos(arg) + i*sin(arg)]
The root values of a number are:
1) root(n) = (x + iy)^(1/n)
2) root(n) = (a*e^(i*arg))^(1/n)
3) root(n,k) = (a*e^i*(arg + 2kPI))^(1/n)
4) root(n,k) = a^(1/n)*(e^i*(arg + 2kPI))^(1/n)
5) root(n,k) = |a^(1/n)|*e^i*(arg + 2kPI)/n
6) root(n,k) = |a^(1/n)|*(cos(arg/n+2kPI/n) + i*sin(arg/n+2kPI/n))
define mag = |a^(1/n)|, theta = arg/n, and delta = 2PI/n
7) root(n,k)= mag*[cos(theta + k*delta) + i*sin(theta + k*delta)], k=0..n-1
Thus, there are n distinct roots (values).
For integer numbers:
For binary based (digital) computers (cpu), all integers are represented as
binary numbers. To find the root 'n' of an integer 'num' we can use the following
process to find the largest integer nth 'root' such that root**n <= num.
For an integer composed of 'b' bits an nth root 'n' will have at most (b/n + 1) bits.
For squareroots n = 2:
For 9 = 0b1001, it has b = 4 bits, and its squareroot has at most (4/2 + 1) = 3 bits.
The squareroot of 9 is 3 = 0b11, which is 2 bits.
For 100 = 0b1100100, b = 7, and its squareroot has at most (7/2 + 1) = 4 bits.
The squareroot of 100 is 10 = 0b1010, which is 4 bits.
For cuberoots n = 3:
For 8 = 0b1000, it has b = 4 bits, and its cuberoot has at most (4/3 + 1) = 2 bits.
The cuberoot of 8 is 2 = 0b10, which is 2 bits.
For 125 = 0b1111101, b = 7, and its cuberoot has at most (7/3 + 1) = 3 bits.
The cuberoot of 125 is 5 = 0b101, which is 3 bits.
Algorithm:
bits_shift = (num.bit_length)/n + 1 # determine max number of root bits
bitn_mask = 1 << bits_shift # set value for max bit position of root
root = 0 # initialize the value for root
until bitn_mask == 0 # step through all the bit positions for root
root |= bitn_mask # set current bit position to '1' in root
root ^= bitn_mask if root**n > num # set it back to '0' if root too large
bitn_mask >>= 1 # set bitn_mask to next smaller bit position
end
root # return exact integer value for root
Starting with 2.1.0 Newton's method for squareroots is used instead of bbm.
Starting with 2.2.0 Newton's method for general nth roots is used instead of bbm.
https://en.wikipedia.org/wiki/Nth_root_algorithm
Jabari Zakiya
GPL-2.0+