【问题标题】:How to pretty-print decimal format如何漂亮地打印十进制格式
【发布时间】:2017-09-16 08:04:43
【问题描述】:

当我漂亮打印它们时,有没有办法改变小数的默认格式?

irb(main):521:0> pp 10.to_d / 2.5   
0.4e1

我想把它格式化为:

irb(main):521:0> pp 10.to_d / 2.5   
4.0

我并不真正关心潜在的精度损失。当您漂亮地打印 Rails 记录时,默认格式尤其令人讨厌:

<
  ...  
  id: 49391,  
  operator_id: 1,  
  tax_rate: 0.10e2,  
  sales_price: 0.1e2,  
  unit_price: 0.2e1,  
  >

我知道我可以使用to_sto_f 等,但漂亮打印的全部意义在于我不必转换我的记录就可以快速浏览它们。

【问题讨论】:

    标签: ruby decimal number-formatting pretty-print


    【解决方案1】:

    当您使用 to_dto_f 时,您是在告诉 Ruby 将值转换为 BigDouble 或 Float,但这并没有指定输出格式,这是一个不同的问题。

    Ruby 支持多种格式的字符串格式,但通常您定义一种格式,然后用于“漂亮打印”输出:

    foo = 0.4e1
    '%1.1f' % foo # => "4.0"
    

    请注意,输出是字符串,而不是 Float 或 BigDecimal。在输出到控制台之前,所有内容都转换为字符串。 Ruby 的格式字符串遵循 C、Perl 和许多其他语言使用的sprintf 格式字符串。请参阅sprintf 了解更多信息。

    而且,虽然 sprintf 存在,但我很少看到它被使用。相反,String 的% 方法使用得更多,其次是Kernel 的format 方法。

    还要注意10.to_d / 2.5 是无效的,因为10 是一个Integer,而Integer 不知道如何to_d

    10.class # => Integer
    10.respond_to?(:to_d) # => false
    10.to_d / 2.5    # => NoMethodError: undefined method `to_d' for 10:Integer
    

    需要 BigDecimal 才能获得 to_d

    require 'bigdecimal'
    require 'bigdecimal/util'
    
    10.to_d / 2.5    # => 0.4e1
    

    【讨论】:

      【解决方案2】:

      在 Ruby 2.4 中,BigDecimal#inspect 等同于 BigDecimal#to_s,它始终默认使用科学计数法。

      decimal = 10.to_d / 2.5
      decimal.inspect
      # => "0.4e1"
      
      # equivalent to
      decimal.to_s
      # => "0.4e1"
      

      幸运的是,该类接受其to_s 方法的参数,该方法允许您指定结果字符串的格式。在其他选项中,您可以指定是否需要科学记数法或常规浮点记数法。因此,通过如下使用它,您可以获得您想要的结果:

      decimal.to_s("F")
      # => "4.0"
      

      The documentation of BigDecimal#to_s 详细介绍了如何设置更多格式选项。

      不幸的是,对于您明显的用例,Ruby 无法更改默认格式。为了获得浮点表示法,您始终必须将"F" 参数显式添加到to_s 方法。

      【讨论】:

        【解决方案3】:

        您可以对漂亮打印机使用的方法进行猴子补丁。 “普通”IRb 使用inspect,但大多数漂亮的打印机库都有自己的方法。

        例如,标准库中的pp library 使用称为pretty_print 的方法。不幸的是,BigDecimal 没有自己的pretty_print 实现,它只是从Numeric 继承了一个,它只是委托给inspect

        所以,我们可以自己写!

        class BigDecimal
          def pretty_print(pp)
            pp.text to_s('F')
          end
        end
        
        pp 10.to_d / 2.5
        # 4.0
        

        【讨论】:

        • 谢谢,正是我想要的!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-06
        • 2012-05-04
        • 2015-01-22
        • 1970-01-01
        • 1970-01-01
        • 2019-10-08
        • 2011-01-07
        相关资源
        最近更新 更多