如何漂亮地打印十进制格式

How to pretty-print decimal format

有没有办法在我漂亮地打印小数时更改小数的默认格式?

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 等,但是 pretty-print 的全部意义在于我不必转换我的记录就可以拥有快速浏览一下。

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

Ruby 支持几种风格的字符串格式化,但通常您定义一种格式,然后用于 "pretty-print" 输出:

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

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

而且,虽然 sprintf 存在,但我很少看到它被使用。取而代之的是 String 的 % method is used more often, followed by Kernel's format 方法。

另请注意,10.to_d / 2.5 无效,因为 10 是一个整数,而整数不知道如何 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

在 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"

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

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

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

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

您可以对漂亮打印机使用的方法进行猴子修补。 "Normal" 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