Mathematical formulas in Ruby

Tomek Wielgocki

Problem

How to evaluate this formula:

2*height*(width + length)

for given values of height, width and length?

Solution #1 (naive)

Kernel#eval

formula = '2*height*(width + length)'
variables = { 'height' => 3, 'width' => 4, 'length' => 5 }

variables.each do |key, value|
  formula.gsub!(key, value)
end

eval(formula)

Solution #2

Improved Kernel#eval

VALID_EXPRESSION = /\A[0-9\.\+\-\*\/\(\)]*\z/
formula = '2*height*(width + length)'
variables = { 'height' => 3, 'width' => 4, 'length' => 5 }

variables.each do |key, value|
  formula.gsub!(key, value)
end

if VALID_EXPRESSION =~ formula
  eval(formula)
else
  raise 'Invalid formula'
end

Solution #3 (pro)

Abstract Syntax Tree (AST)

Do we have to implement it?

No! We have Dentaku!

formula = '2*height*(width + length)'
variables = { 'height' => 3, 'width' => 4, 'length' => 5 }

calculator = Dentaku::Calculator.new
calculator.evaluate!(formula, variables)

Support for case sensitivity:

formula = '2*HEIGHT*(width + length)'
variables = { 'height' => 3, 'width' => 4, 'length' => 5 }

calculator = Dentaku::Calculator.new(case_sensitive: true)
calculator.evaluate!(formula, variables) # ERROR!

Support for functions:

formula = 'roundup(2*radius*PI)'
variables = { 'radius' => 4.75, 'PI' => 3.14 }

calculator = Dentaku::Calculator.new
calculator.evaluate!(formula, variables)

Demo

Contact

https://github.com/tiwi/mathematical-formulas

tomek@railwaymen.org

Join our team!

https://railwaymen.org/

praca@railwaymen.org

Questions?