Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pretty-print decimal format

Is there a way to change the default format of decimals when I pretty-print them?

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

I would like to format it as:

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

I don't really care about potential precision loss. The default format is especially annoying to read when you're pretty-printing Rails records:

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

I know that I can do to_s or to_f, etc., but the whole point of pretty-print is that I don't have to convert my records before I can have a quick glance at them.

like image 291
Zyphrax Avatar asked Jan 23 '26 09:01

Zyphrax


2 Answers

You could monkey-patch the method the pretty-printer uses. "Normal" IRb uses inspect, but most of the pretty-printer libraries have their own methods.

For example, the pp library from the standard library uses a method called pretty_print. BigDecimal doesn't have its own implementation of pretty_print unfortunately, it simply inherits the one from Numeric which just delegates to inspect.

So, we can write our own!

class BigDecimal
  def pretty_print(pp)
    pp.text to_s('F')
  end
end

pp 10.to_d / 2.5
# 4.0
like image 115
Jörg W Mittag Avatar answered Jan 24 '26 23:01

Jörg W Mittag


When you use to_d or to_f you're telling Ruby to convert the value to a BigDouble or Float, but that doesn't specify output format, which is a different problem.

Ruby supports string formatting in a couple flavors, but generally you define a format that is then used to "pretty-print" the output:

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

Note that the output is a string, not a Float or BigDecimal. Everything is converted to a String before being output to the console. Ruby's format strings follow the sprintf format strings used by C, Perl and many other languages. See sprintf for more information.

And, while sprintf exists, I rarely see it used. Instead String's % method is used more often, followed by Kernel's format method.

Also note that 10.to_d / 2.5 is invalid because 10 is an Integer, and Integer doesn't know how to to_d:

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

Requiring BigDecimal is necessary to get to_d:

require 'bigdecimal'
require 'bigdecimal/util'

10.to_d / 2.5    # => 0.4e1
like image 40
the Tin Man Avatar answered Jan 24 '26 22:01

the Tin Man