【问题标题】:Ruby eval without round [duplicate]没有圆形的Ruby eval [重复]
【发布时间】:2013-12-22 20:07:19
【问题描述】:

我有一个净化过的字符串,我想使用 ruby​​ eval 进行评估。该字符串可以包含任何简单的算术公式,例如“44/5”。

问题是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') 给了我想要的结果,但我不想在字符串中插入任何东西(我准备在必要时将其包装起来)。

知道如何解决这个问题吗?

【问题讨论】:

    标签: ruby


    【解决方案1】:

    这里使用Rational#to_f:

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

    【讨论】:

    • 字符串有一个to_rmethod: '44/5'.to_r
    • @steenslag 是的..'44/5'.to_r # => (44/5),但之后需要调用#to_f。无论如何,我也添加了..谢谢
    • 在我的情况下它并没有真正的帮助(正如我所说的字符串可以表示任何算术公式,例如'2+3/4')
    • @Alexander 我不明白你。接受的答案与这个答案有何不同?阅读你的问题,我可以看到 - 你的问题是 - 你得到 8,而你正在寻找 8.8。
    【解决方案2】:

    你也可以使用mathn from Ruby's core library:

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

    这个库会在适当的时候自动转换为有理数。

    【讨论】:

    • 这太棒了 +1 因为知识认为这需要添加到 ruby​​ 文档中
    • @bjhaid 它在文档中 ;-) 我已经链接到它。
    • 文档没有解释你得到了一个 Rational 对象(对象类型),它对某些人来说并不简单,只需要检查 pry/irb 就知道它是一个理性对象
    • 啊,我明白你的意思了。是的,这是个好主意。
    • 非常感谢! +1 并接受答案。
    【解决方案3】:

    我没有找到任何额外的 eval 参数来管理它。

    因为eval 适用于所有事物,而不仅仅是数学方程式。

    Arup 的 solution 看起来更好,但这是我的:

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

    ps。第二个字符串 (1.0*(44/5)) 不起作用,因为首先计算 (44/5) (8 = 整数),然后乘以 1.0(= 8.0)。

    【讨论】:

      【解决方案4】:

      不知道为什么没有人提到强制浮点数在除数中放置一个浮点数。即

      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
      

      也可以使用括号和现有的浮点数

       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
      

      非常简单,无需额外的库。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-24
        • 1970-01-01
        • 2020-12-29
        • 1970-01-01
        • 2021-01-29
        • 2016-10-08
        • 1970-01-01
        相关资源
        最近更新 更多