How to get nth root of a number in Ruby? - ruby

For example
x ** 3 # => 125
Knowing that the result of applying ** with an argument 3 to x is 125, how can I get the value of x?
Is there some kind of built-in method for this? I have been looking at the Math module but didn't find anything similar.

Using ** with 1/3:
125 ** (1.0/3)
# => 4.999999999999999

You could also try as below :
irb(main):005:0> 125**(3**-1)
=> 5
irb(main):006:0> 125**(3**-1.0)
=> 4.999999999999999
irb(main):007:0>
update
C:\Users >ruby -v
ruby 1.9.3p448 (2013-06-27) [i386-mingw32]

You can do an Nth root by raising to a fractional power. For example, the 4th root of 625 is 5.
(BigDecimal.new(625)**(1.0/4.0)).to_f
# => 5.0
Note, the .to_f is added for readability in this answer only. Don't cast it to a Float in your code unless you need to. IMHO, BigDecimals are "better" than Floats in Ruby - Floats lose precision too easily and you won't get accurate results. Case in point the accepted awnser above. The cube root of 125 is not 4.99999(repeat). It is 5.0 exactly.
Edit: the Ruby Class Rational seems to handle nth roots a little better.
2.3.3 :007 > 625.to_r ** 0.25
=> 5.0
But it still isn't as precise with a number that produces an irrational root.
2.3.3 :024 > (999.to_r ** 0.25) ** 4
=> 998.9999999999999
Close...but you should be able to get back to 999.0 exactly. My Mac's calculator and excel can do it. Main point - just be careful. If precision is important, Ruby may not handle this exactly the way one would expect.

Related

What does the .size on number mean in ruby?

Why is my ruby giving incorrect size of number? It doesn't matter what's the number. The output is always 4 for the size. What does that mean? I always thought it should give the number of digits.
number = 14
print number
print "\n"
print number.size
output:
14
4
ruby version
ruby 2.1.8p440 (2015-12-16 revision 53160) [i386-mingw32]
I always suggest to check the method you're not sure about using the following scheme:
Check where the method comes from (using Object#method):
number.method(:size)
#=> #<Method: Fixnum#size>
Open docs and learn what it does for Fixnum#size and how it works.
2.1 If you're using IRB, you can run help 'Fixnum#size' to get the docs right in your console
2.2 If you're using pry, you can go with show-doc Fixnum#size (install pry-doc gem first)
In Ruby 2.1.8 method was defined in Fixnum#size.
Starting from Ruby 2.4 it's defined in
Integer#size:
Returns the number of bytes in the machine representation of int.
You are confusing the two methods String#size:
Returns the character length of str.
and Fixnum#size:
Returns the number of bytes in the machine representation of fix.
14 is an object of class Fixnum, so when you call size on it you are getting the number of bytes in the machine representation of the number.
If you would like to know how many digits there are in a number, you can simply convert it to a string first and then call size on that:
14.to_s
# => "14"
14.to_s.size
#=> 2
12345.to_s.size
#=> 5

Why is .object_id in ruby sometimes returning positive or negative numbers?

I get this for a nil object in Ruby (irb):
nil.object_id # => 4
But for a string, I get negative results:
"abc".object_id # => -570954278
"abc".object_id # => -570956148
I am confused about the negative part. Is this proper or have I done something strange?
My ruby is:
ruby 2.3.0p0 (2015-12-25 revision 53290) [i686-linux]
The number effectively is a signed integer, with one bit used for sign and the rest used for data. See here for a discussion on some finer points of its implementation, mentioning the positive and negative storage.
But to be short, no, there isn't anything to worry about.

Comparing two virtually identical BigDecimal numbers in Ruby on Rails

I got a little problem that I really would like to understand. I am using assert_equal to compare two BigDecimal numbers that are supposed to be identical. They actually are except a very little tiny fraction, see below:
-#<BigDecimal:7f4b40e8de78,'0.4021666666 6666666666 666666667E2',36(45)>
+#<BigDecimal:7f4b40e85db8,'0.4021666666 6666666666 6666668E2',36(63)>
I use assert_in_delta in order to not fail the test cases. So I got a reasonable workaround. I do wonder though whether it would be possible to have it equal:
assert_equal (241.30.to_d/6), model.division_function
The model's division_function does exactly the same. It divides a BigDecimal of value 241.3 by the length of an array, which is 6.
There seems to be a very tiny difference in the precision.
I would like to know where that might come from?
Is there a way I can control precision more accurately?
EDIT
I am using Mongoid. It is worth to note that Mongoid offers BigDecimal as a field type, but it is stored as a string. However, I don't think this is the problem. I believe it is a Ruby thing.
EDIT
I got a little further with an example which hints that it is a Ruby issue and not directly related to Rails. Please see below:
irb(main):041:0* amount1 = BigDecimal("241.3")
=> #<BigDecimal:7f49bcb03558,'0.2413E3',18(18)>
irb(main):042:0> amount2 = BigDecimal("1800")
=> #<BigDecimal:7f49bcaf3400,'0.18E4',9(18)>
irb(main):043:0> rate = amount1 / amount2
=> #<BigDecimal:7f49bcae8398,'0.1340555555 5555555555 5555556E0',27(45)>
irb(main):044:0> rate * amount2 #should return amount1 = 241.3, but it does not :-(
=> #<BigDecimal:7f49bcad6a30,'0.2413000000 0000000000 00000008E3',36(45)>
irb(main):045:0>
I reported the bug to the Ruby core team. However, this is not a bug as you can see in the rejection response.
BigDecimal, though offers arbitrary precision, cannot represent numbers like 1/3 precisely. Thus during some arithmetic you can encounter imprecisions.
You can use Rational in Ruby for exact numbers. Exercise caution when doing arithmetics if you wish to keep the result exact.

Is the frozen behavior on Fixnum a specified behavior?

Here was the behavior that somewhat surprised me:
1.9.3-p392 :001 > n = 1
=> 1
1.9.3-p392 :002 > n.frozen?
=> false
1.9.3-p392 :003 > 1.freeze
=> 1
1.9.3-p392 :004 > n.frozen?
=> true
I tried grepping through the RubySpec source code for frozen and I didn't see anything about Fixnums at all.
Is this behavior the same as what would be expected on non-MRI Ruby implementations? If I run n = 1; 1.freeze; n.frozen?, will the final result always be true on any Ruby implementation? Why or why not?
It looks like it is an intended feature. In Ruby Forum, a question is raised:
Isn't technically all Fixnums "frozen" (because you can't modify the state)?
to which matz answers:
Not really, since fixnums could have instance variables.
Thus, theoretically, there's room for freezing fixnums. I don't think it's worth the cost though.
There seems to have been unintended inconsistency between different MRI Ruby versions, but as far as MRI is concerned, they look like they were identified as bugs, and were fixed. The specification you observed seems to be the intended one.
Since everything in Ruby is an object, it perhaps shouldn't be surprising that you can freeze 1. Symbol has the same behavior. As mentioned in the comments, this behavior changed from 1.8.7 (freezing didn't do anything) to 1.9+ (freezing works).
What might be more surprising is that freezing 1 also freezes n. According to the documentation for Fixnum,
There is effectively only one Fixnum object instance for any given
integer value
This means that n and 1 are references to the same object, and modifying one will modify the other.
You can check this for yourself by looking at the object_id.
1.object_id
=> 3
n=1
n.object_id
=> 3
n.equal? 1
=> true
I tried this code in MRI 1.8.7, MRI 2.0.0, JRuby, and Rubinius and got the same result.

Is there a Ruby gem or library that provides a way to parse ordinal numbers?

I'm looking for a way to parse ordinal numbers (first, second, third, etc) in Ruby and convert them to integers. Do you know of any libraries that do this?
I was half-way through asking this question when I realized that the chronic gem does this as part of the process of parsing dates. After installing the gem, you can convert ordinal numbers to integers pretty easily:
irb(main):001:0> require 'chronic'
=> true
irb(main):002:0> Chronic::Numerizer.numerize("eighty-fifth").to_i
=> 85
Edit: Unfortunately, it seems that chronic doesn't correctly parse the ordinal "second":
irb(main):003:0> Chronic::Numerizer.numerize("twenty-second").to_i
=> 20
The reason for this is that chronic is designed to parse dates and times, and "second" could be either an ordinal number or a unit of time in that context. To solve this problem, you can monkey patch chronic's Numerizer class with this line:
Chronic::Numerizer::ORDINALS.insert(1, ['second', '2'])
Now it works:
irb(main):005:0> Chronic::Numerizer.numerize("eighty-second").to_i
=> 82
If you are actually using chronic for its intended purpose though, you probably won't want to screw with its internals. In that case, you can copy the source code from Chronic::Numerizer into a new class and use that one instead. Don't forget to add ['second', '2'] to the ORDINALS constant in the new class.
There's a gem called numerouno which seems to be specifically targeted at this, if Chronic doesn't fit your use case.
I've been using a gem called deordinalize (https://rubygems.org/gems/deordinalize) which seems to do the trick nicely - just make sure you downcase before calling;
>> require 'deordinalize'
>> 'Forty-Second'.downcase.deordinalize
=> 42
To correctly parse the ordinal "second":
you have now to monkey patch Numerizer class with this line
SINGLE_ORDINALS.insert(1, ['second', 2])

Resources