Arithmetic in ruby
What Every Computer Scientist Should Know About Floating-Point Arithmetic
Write Multiline Arithmetic in Ruby
The Ruby parser will assume a statement has ended if it looks like it has ended at an end of the line.
What you can to do prevent that is to leave the arithmetic operator just before a new line, like this:
a = 1
b = 2
c = a +
b
And you'll get the result you expect.
Perform arithmetic operations on string in Ruby
While I hesitate to answer an interview question, and I am completely embarrassed by this code, here is one awful way to do it. I made it Ruby-only and avoided Rails helpers because it seemed more of a Ruby task and not a Rails task.
#
# Evaluate a string representation of an arithmetic formula provided only these operations are expected:
# + | Addition
# - | Subtraction
# * | Multiplication
# / | Division
#
# Also assumes only integers are given for numerics.
# Not designed to handle division by zero.
#
# Example input: '20+10/5-1*2'
# Expected output: 20.0
#
def eval_for_interview(string)
add_split = string.split('+')
subtract_split = add_split.map{ |v| v.split('-') }
divide_split = subtract_split.map do |i|
i.map{ |v| v.split('/') }
end
multiply_these = divide_split.map do |i|
i.map do |j|
j.map{ |v| v.split('*') }
end
end
divide_these = multiply_these.each do |i|
i.each do |j|
j.map! do |k, l|
if l == nil
k.to_i
else
k.to_i * l.to_i
end
end
end
end
subtract_these = divide_these.each do |i|
i.map! do |j, k|
if k == nil
j.to_i
else
j.to_f / k.to_f
end
end
end
add_these = subtract_these.map! do |i, j|
if j == nil
i.to_f
else
i.to_f - j.to_f
end
end
add_these.sum
end
Here is some example output:
eval_for_interview('1+1')
=> 2.0
eval_for_interview('1-1')
=> 0.0
eval_for_interview('1*1')
=> 1.0
eval_for_interview('1/1')
=> 1.0
eval_for_interview('1+2-3*4')
=> -9.0
eval_for_interview('1+2-3/4')
=> 2.25
eval_for_interview('1+2*3/4')
=> 2.5
eval_for_interview('1-2*3/4')
=> -0.5
eval_for_interview('20+10/5-1*2')
=> 20.0
eval_for_interview('20+10/5-1*2*4-2/6+12-1-1-1')
=> 31.0
Arithmetic series in Ruby
If an array arr
contains integer values, those (ordered) values comprise at most one arithmetic expression. If the average interval is integer-valued (i.e.,
((arr.last-arr.first) % (arr.size-1).zero?
is true), a unique progression is given by the values of arr.first
, arr.last
and arr.size
, namely:
avg_interval = (arr.last-arr.first)/(arr.size-1)
(arr.first..arr.last).step(avg_interval).to_a
If the average interval is not integer-valued, it cannot be an arithmetic progression, but we don't need to check that condition. That's because by using integer arithmetic to compute avg_interval
, the resulting arithmetic progression cannot equal arr
if the average interval is not integer-valued.
Hence, rather than check if all the intervals are equal, we could just check to see if the above arithmetic progression equals arr
.
Code
def arithmetic_progression?(arr)
return true if arr.size < 2
(arr.first..arr.last).step((arr.last-arr.first)/(arr.size-1)).to_a == arr
end
Examples
arithmetic_progression?([1,3,5,7,9]) #=> true
arithmetic_progression?([1,3,5,7,8]) #=> false
In the first example:
arr = [1,3,5,7,9]
avg_interval = (arr.last-arr.first)/(arr.size-1) #=> 2
(arr.first..arr.last).step(avg_interval).to_a #=> [1, 3, 5, 7, 9]
In the second:
arr = [1,3,5,7,8]
avg_interval = (arr.last-arr.first)/(arr.size-1) #=> 1
(arr.first..arr.last).step(avg_interval).to_a #=> [1, 2, 3, 4, 5, 6, 7, 8]
You could then write, for example:
arithmetic_progression?([1,3,5,7,9]) ? "Arithmetic progression" :
"Not arithmetic progression" #=> "Arithmetic progression"
Variant
The method could probably be made slightly more efficient by inserting the following line after the first line of the method:
return false unless ((arr.last-arr.first) % (arr.size-1)).zero?
Why is division in Ruby returning an integer instead of decimal value?
It’s doing integer division. You can make one of the numbers a Float
by adding .0
:
9.0 / 5 #=> 1.8
9 / 5.0 #=> 1.8
Ruby language curious integer arithmetic : (-5/2) != -(5/2)
Why does this happen?
It's not quite clear what kind of answer your are looking for other than because that is how it is specified (bold emphasis mine):
15.2.8.3.4
Integer#/
/(
other)
- Visibility: public
- Behavior:
- a) If other is an instance of the class
Integer
:
- 1) If the value of other is 0, raise a direct instance of the class
ZeroDivisionError
.- 2) Otherwise, let n be the value of the receiver divided by the value of other. Return an instance of the class
Integer
whose value is the largest integer smaller than or equal to n.
NOTE The behavior is the same even if the receiver has a negative value. For example,-5 / 2
returns-3
.
As you can see, the specification even contains your exact example.
It is also specified in the Ruby/Spec:
it "supports dividing negative numbers" do
(-1 / 10).should == -1
end
Compare this with the specification for Float#to_i
(bold emphasis mine):
15.2.9.3.14
Float#to_i
to_i
- Visibility: public
- Behavior: The method returns an instance of the class
Integer
whose value is the integer part of the receiver.
And in the Ruby/Spec:
it "returns self truncated to an Integer" do
899.2.send(@method).should eql(899)
-1.122256e-45.send(@method).should eql(0)
5_213_451.9201.send(@method).should eql(5213451)
1.233450999123389e+12.send(@method).should eql(1233450999123)
-9223372036854775808.1.send(@method).should eql(-9223372036854775808)
9223372036854775808.1.send(@method).should eql(9223372036854775808)
end
Micro dsl for arithmetic in Ruby
Actually, it's quite simple:
def whats expr; expr end
whats 1 + 1
# => 2
Arithmetic sequence Ruby
requirement is that we need to take user input in a single line instead of taking in multiple line, split that and store in an array
gets.chomp
returns a string with trailing newline removed, e.g. (the 2nd line being user input)
x = gets.chomp
2 4 6 8 12 14
x #=> "2 4 6 8 12 14"
split
converts that string to an array:
x.split
#=> ["2", "4", "6", "8", "12", "14"]
what's missing is the conversion to integer. To convert each element of an array, there's map
:
x.split.map { |s| s.to_i }
#=> => [2, 4, 6, 8, 12, 14]
or its short-hand notation:
x.split.map(&:to_i)
#=> => [2, 4, 6, 8, 12, 14]
applied to your code:
puts "enter arithmetic sequence"
x = gets.chomp
o = x.split.map(&:to_i)
puts "#{o}"
# ...
Note that there's no need to create an empty array. You can just assign the result of map
to o
.
The rest of your code seems to work as expected. But you should check out Cary Swoveland's answer for more succinct way of finding the missing element.
Arbitrary precision arithmetic with Ruby
Simple: it does it the same way you do, ever since first grade. Except it doesn't compute in base 10, it computes in base 4 billion (and change).
Think about it: with our number system, we can only represent numbers from 0
to 9
. So, how can we compute 6+7
without overflowing? Easy: we do actually overflow! We cannot represent the result of 6+7
as a number between 0
and 9
, but we can overflow to the next place and represent it as two numbers between 0
and 9
: 3×100 + 1×101. If you want to add two numbers, you add them digit-wise from the right and overflow ("carry") to the left. If you want to multiply two numbers, you have to multiply every digit of one number individually with the other number, then add up the intermediate results.
BigNum arithmetic (this is what this kind of arithmetic where the numbers are bigger than the native machine numbers is usually called) works basically the same way. Except that the base is not 10, and its not 2, either – it's the size of a native machine integer. So, on a 32 bit machine, it would be base 232 or 4 294 967 296.
Specifically, in Ruby Integer
is actually an abstract class that is never instianted. Instead, it has two subclasses, Fixnum
and Bignum
, and numbers automagically migrate between them, depending on their size. In MRI and YARV, Fixnum can hold a 31 or 63 bit signed integer (one bit is used for tagging) depending on the native word size of the machine. In JRuby, a Fixnum can hold a full 64 bit signed integer, even on an 32 bit machine.
The simplest operation is adding two numbers. And if you look at the implementation of +
or rather bigadd_core
in YARV's bignum.c, it's not too bad to follow. I can't read C either, but you can cleary see how it loops over the individual digits.
Related Topics
How to Write an Rspec Test for a Ruby Method That Contains "Gets.Chomp"
How to Memoize a Method That May Return True, False, or Nil in Ruby
If 'Main' Is an Instance of 'Object', Why Can't I Call It
How to Get the Final Url After Redirects Using Ruby
Add a CSS Class to <%= F.Submit %>
Can't Run Bundle Update on Windows
Encoding::Undefinedconversionerror: "\Xe4" from Ascii-8Bit to Utf-8
Rails 3, Displaying Jpg Images from the Local File System Above Rails_Root
How to Determine If a String Is Numeric
Subtract Values in Hash from Corresponding Values in Another Hash
How to Run Ruby on Rails Applications on a Windows Box
Problem Using Openstruct with Erb
Ruby: Building a Plot of Function
Automatically Open a File as Binary with Ruby
Adding a Background Image in Ruby on Rails 2 in CSS
Enable Dropping a File Onto a Ruby Script
Difference Between Lambda and -> Operator in Ruby
Erroneous "Insecure World Writable Dir Foo in Path" When Running Ruby Script