Ruby-on-rails evaluation of mathementical expression - ruby-on-rails

In Ruby-on-rails, I am receiving input from a call to a XL macro(currently hard coded), which places a mathematical expression in the spreadsheet. If I call the macro I will receive a worksheet with an expression like this in one of the cells
x + ( 3 / 12)
In the R-O-R application I wish to take this expression and evaluate for different values of x.
row.each do |row|
y = row
end
I want to find the value of y for say example x = 2 ? Should I receive this expression as a literal ?

There is no built-in function to do this securely. You need a math parser and evaluator. You can write one yourself or you could use an existing one like Dentaku.

eval and gsub will get you most of the way there. Fire up irb:
(533)⚡️ irb
2.1.2 :001 > exp = 'x + (3 / 12)'
=> "x + (3 / 12)"
2.1.2 :002 > eval(exp.gsub(/x/, '25'))
=> 25
2.1.2 :003 > exp = 'x + (4.0 / 25.0) + 4'
=> "x + (4.0 / 25.0) + 4"
2.1.2 :004 > eval(exp.gsub(/x/, '25'))
=> 29.16
Notice the result of command 002. Ruby is assuming the 3 / 12 is integer math, so the result will be an integer, which is 0 in this case. In 003 floating point math occurs because the numbers are decimals. This aspect may be an issue you need to tackle more creatively, or just make sure your expressions conform to the type of math you need to occur.
Be aware of the security concerns with eval, you're executing Ruby code in there, so mean people may put mean things in there to try and execute it.

Why not write a one line function, as following:
def foo(x) x + (3 / 12) end
Now you can use this to calculate any value of x, for x = 2, you can do: foo(2) or foo 2.

Related

Printing to specific (runtime-determined) precision in Julia

Given a value x and an integer n (assigned at runtime), I want to print x to exactly n digits after the decimal (after rounding if needed).
print(round(x, n)) works fine for (x,n)=(3.141592, 3) but for (x,n)=(2.5,5), it prints just 2.5, not 2.50000 (5 digits after decimal point).
If I knew n at runtime, say 5, I could do
#printf("%.5f", x)
But #printf being a macro needs n to be known at compile time.
Is this possible using some show magic or something else?
Using the fresh new Format.jl package:
using Format
function foo(x, n)
f = FormatSpec(".$(n)f")
pyfmt(f, x)
end
foo(2.5, 5)
Unfortunately, for some reason the julia version of #printf / #sprintf do not support the "width" sub-specifier as per the c printf standard (see man 3 printf).
If you're feeling brave, you can rely on the c sprintf which supports the "dynamic width" modifier, to collect a string that you then just print as normal.
A = Vector{UInt8}(100); # initialise array of 100 "chars"
ccall( :sprintf, Int32, (Ptr{UInt8}, Cstring, Int64, Float64), A, "%.*f", 4, 0.1 )
print( unsafe_string(pointer(A)) ) #> 0.1000
Note the asterisk in %.*f, and the extra input 4 serving as the dynamic width modifier.

ruby round off to two decimal place and keep zero [duplicate]

This question already has answers here:
to_d to always return 2 decimals places in ruby
(5 answers)
Closed 7 years ago.
i want to round off a number upto two decimal place in ruby such that
(0.02 * 270187).round(2) is 5403.74 which is correct
but
(0.02 * 278290).round(2) is 5565.8 which is not consistent with previous one
i want to make it look like 5565.80
Please tell me how can i do it in ruby
This will do the trick:
> sprintf("%.2f",(0.02 * 270187))
#=> "5403.74"
> sprintf("%.2f",(0.02 * 278290))
#=> "5565.80"
> sprintf("%.2f",(0.02 * 270187)).to_f > 100 # If you plan to Compare something with result
#=> true
OR
> '%.2f' % (0.02 * 270187)
#=> "5403.74"
> '%.2f' % (0.02 * 278290)
#=> "5565.80"
Demo
Note: The result is always a string, but since you're rounding I assume you're doing it for presentation purposes anyway. sprintf can format any number almost any way you like. If you are planning to compare anything with this result then convert this string to float by adding .to_f at the end. Like this
You could do something like
include ActionView::Helpers::NumberHelper
number_with_precision(value, :precision => 2) # value.to_f if you have string
or like this
'%.2f' % your_value
Hope it helps!
Further you can read from here

How can I have multiple lines in the ruby interactive shell?

This might be a silly question. But, I am a newb... How can you have a multi-line code in the interactive ruby shell? It seems like you can only have one long line. Pressing enter runs the code. Is there anyway I can skip down to the next line without running the code? Again, sorry if this is a dumb question. Thanks.
This is an example:
2.1.2 :053 > a = 1
=> 1
2.1.2 :054 > b = 2
=> 2
2.1.2 :055 > a + b
=> 3
2.1.2 :056 > if a > b #The code ‘if ..." starts the definition of the conditional statement.
2.1.2 :057?> puts "false"
2.1.2 :058?> else
2.1.2 :059 > puts "true"
2.1.2 :060?> end #The "end" tells Ruby we’re done the conditional statement.
"true" # output
=> nil # returned value
IRB can tell us the result of the last expression it evaluated.
You can get more useful information from here(https://www.ruby-lang.org/en/documentation/quickstart/).
One quick way to do this is to wrap the code in if true. Code will run when you close the if block.
if true
User.where('foo > 1')
.map { |u| u.username }
end
If you are talking about entering a multi-line function, IRB won't register it until you enter the final end statement.
If you are talking about a lot of individual expressions such as
x = 1
y = 2
z = x + y
It's OK if IRB executes each as you enter it. The end result will be the same (for time-insensitive code of course). If you still want a sequence of expressions executed as fast as possible, you can simply define them inside of a function, and then run that function at the end.
def f()
x = 1
y = 2
z = x + y
end
f()

Round date to first year of the decade in Ruby

In Rails, I have a date saved in an instance variable. I need to grab the beginning of the decade before it. If #date.year= 1968 then I need to return 1960. How would I do that?
You can do this several ways. As suggested, you can always use integer division which divides the number and truncates the remainder. So 1968/10 returns 196 and if you multiply it by 10, it will give you 1960. Or simply,
#date.year = #date.year/10 * 10
#date.year
=> 1960
I prefer the method of using modular arithmetic. If you do #date.year % 10 it will return the remainder if you divide by 10 which you can then subtract from the year like so:
#date.year = #date.year - (#date.year % 10)
#date.year
=> 1960
The reason I prefer the latter is because integer division truncating the remainder may not be some thing that is obvious to everyone looking at your code. However, modular arithmetic works generally the same in all programming languages.
Keep in mind if you're trying to change the date, you need to use the appropriate method.
#date.change(:year => 1960)
just divide and multiply integers: try #date.year/10*10
Do an integer division by 10, and then multiply by 10.
1.9.3-p286 :001 > 1855/10
=> 185
1.9.3-p286 :002 > 185 * 10
=> 1850
The reason why this works (in Ruby, and in C/C++, Python, and possibly many other languages), is that integer division will always truncate the remainder. This will not be the case if you are dividing by a floating point however.

How to cap and round number in ruby

I would like to "cap" a number in Ruby (on Rails).
For instance, I have, as a result of a function, a float but I need an int.
I have very specific instructions, here are some examples:
If I get 1.5 I want 2 but if I get 2.0 I want 2 (and not 3)
Doing number.round(0) + 1 won't work.
I could write a function to do this but I am sure one already exists.
If, nevertheless, it does not exist, where should I create my cap function?
Try ceil:
1.5.ceil => 2
2.0.ceil => 2
How about number.ceil?
This returns the smallest Integer greater than or equal to number.
Be careful if you are using this with negative numbers, make sure it does what you expect:
1.5.ceil #=> 2
2.0.ceil #=> 2
(-1.5).ceil #=> -1
(-2.0).ceil #=> -2
.ceil is good, but remember, even smallest value in float will cause this:
a = 17.00000000000002
17.0
a.ceil
18
Use Numeric#ceil:
irb(main):001:0> 1.5.ceil
=> 2
irb(main):002:0> 2.0.ceil
=> 2
irb(main):003:0> 1.ceil
=> 1
float.ceil is what you want for positive numbers. Be sure to consider the behavior for negative numbers. That is, do you want -1.5 to "cap" to -1 or -2?

Resources