2013-12-22 86 views
1

我有一個sanitized字符串,我想評估使用ruby eval。該字符串可能包含任何簡單的算術公式,如'44/5'。紅寶石eval無輪

問題是eval('44/5')的結果將是8(而不是8.8)。

它發生作爲評估的一部分(因爲1.0*eval('44/5')給8.0)。

我沒有找到任何額外的eval參數來管理它。

我甚至試過前面或包裹字符串將其轉換爲:

'0.0+44/5' 

'1.0*(44/5)' 

但它仍然沒有給我8.8。

eval('44.0/5')給了我想要的結果,但我不想在字符串中插入任何東西(我準備好只是爲了包裝它,如果有必要)。

任何想法如何解決問題?

回答

4

您還可以使用mathn from Ruby's core library:在適當情況下

require 'mathn' 

res = eval('44/5')  #=> (44/5) 
res.to_f    #=> 8.8 

這個庫會自動轉換到有理數。

+0

這是輝煌的+1爲知識認爲這需要添加到紅寶石文檔 – bjhaid

+0

@bjhaid它是在文檔;-)我已經鏈接到它。 –

+0

該文檔並沒有解釋你得到一個Rational對象(對象類型),它不是一些人的直接,只需要檢查pry/irb知道它是一個理性的對象 – bjhaid

8

這是使用Rational#to_f

Rational('44/5').to_f # => 8.8 
'44/5'.to_r.to_f # => 8.8 
+2

字符串有'to_r'方法:'44 /5'.to_r – steenslag

+0

@steenslag是..''44/5'.to_r#=>(44/5)',但之後'#to_f'需要被稱爲。無論如何,我也補充說,也.. ..謝謝 –

+0

它並沒有真正幫助我的情況(正如我告訴字符串可以代表任何算術公式,例如'2 + 3/4') – Alexander

0

我沒有找到任何額外參數的eval來管理它。

因爲eval適用於所有的事情,不僅僅是數學方程式。

奧雅納solution看起來更好,但這裏是我的:

str = '4/5' 
eval('1.0*'+ str) #0.8 

PS。第二個字符串(1.0*(44/5))將不起作用,因爲首先對(44/5)進行評估(8 =整數),然後乘以1.0(= 8.0)。

0

不知道爲什麼沒有人提到過要強制float將float放在除數中。即

eval('44/5') 
#=> 8 
eval('44/5.0') 
#=> 8.8 

但如果你缺乏對字符串時,它可能會更困難,但控制這樣的工作

eval('44/5'.split("/").map(&:to_f).join("/")) 
#=> 8.8 

使用eval

pattern = /([0-9]\.?[0-9]+|[0-9]+|[+-\/*\(\)])/ 
str = "2+3/4" 
str.scan(pattern).flatten.map{|e| e =~(/[0-9]/) ? e.to_f : e} 
#=> [2.0,"+",3.0,"/",4.0] 
str.scan(pattern).flatten.map{|e| e =~(/[0-9]/) ? e.to_f : e}.join 
#=> "2.0+3.0/4.0" 
eval(str.scan(pattern).flatten.map{|e| e =~(/[0-9]/) ? e.to_f : e}.join) 
#=> 2.75 

工程用括號過於處理多個arthimitic符號和現有浮標

str = "(2+3)/4" 
eval(str.scan(pattern).flatten.map{|e| e =~(/[0-9]/) ? e.to_f : e}.join) 
#=> 1.25 

str = "(2.3+1)/4" 
eval(str.scan(pattern).flatten.map{|e| e =~(/[0-9]/) ? e.to_f : e}.join) 
#=> 0.825 

版本與Rational方法

str = "(2.3+3)/4*2" 
str.to_r.to_f 
#=>0.0 
eval(str.scan(pattern).flatten.map{|e| e =~(/[0-9]/) ? e.to_f : e}.join) 
#=> 2.65 

無需附加的庫很簡單。