Arithmetic in Ruby

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



Leave a reply



Submit