43

I am pretty formatting a floating point number but want it to appear as an integer if there is no relevant floating point number.

I.e.

  • 1.20 -> 1.2x
  • 1.78 -> 1.78x
  • 0.80 -> 0.8x
  • 2.00 -> 2x

I can achieve this with a bit of regex but wondering if there is a sprintf-only way of doing this?

I am doing it rather lazily in ruby like so:

("%0.2fx" % (factor / 100.0)).gsub(/\.?0+x$/,'x')
Bo Jeanes
  • 6,294
  • 4
  • 42
  • 39
  • 4 years later and I realized that that Regexp is subtly misleading. `.gsub(/(\.0+)?x/, 'x')` is probably better... – Bo Jeanes Dec 10 '13 at 22:04
  • A lot of useless answers, the `#gsub` (actually `#sub` should be better) seems like the best option. idk why second expression should be better. If re doesn't match, then string stays the same. – akostadinov May 22 '23 at 21:35
  • @akostadinov 14 years later, I completely agree. At the time, I was just trying to learn `sprintf` and thought there might be something that already did this. There isn't, and a regex is truly the simplest way to do this, IMO. – Bo Jeanes Jun 09 '23 at 02:59

8 Answers8

50

You want to use %g instead of %f:

"%gx" % (factor / 100.00)
Naaff
  • 9,213
  • 3
  • 38
  • 43
  • 2
    awesome. works well in my scenario. Unfortunately though it seems that "%.3gx" doesn't work as I'd expect. the 3 is total digits, not maximum digits after the decimal point. That means 2.12345 will be 2.12 but 22.12345 will be 22.1 instead of 22.12. Luckily in my scenario it doesn't matter, but do you know a way around that? – Bo Jeanes May 08 '09 at 04:38
  • 6
    Formatting with %g will give either the 'natural' representation of the number (without trailing zeros) or the scientific representation (whichever is shorter, basically). %.3g, as you pointed out, sets the total number of digits to 3 rather than setting the number of digits after the decimal point. If you want to control the number of digits after the decimal point you need to use %f, as %.3f specifies 3 digits after the decimal point (padding with 0, if necessary). Unfortunately, I don't know of a way to mix and match these two alternatives. – Naaff May 08 '09 at 05:00
30

You can mix and match %g and %f like so:

"%g" % ("%.2f" % number)
gylaz
  • 13,221
  • 8
  • 52
  • 58
27

If you're using rails, you can use rails' NumberHelper methods: http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html

number_with_precision(13.001, precision: 2, strip_insignificant_zeros: true)
# => 13
number_with_precision(13.005, precision: 2, strip_insignificant_zeros: true)
# => 13.01

Be careful, because precision means all digits after decimal point in this case.

Viktor
  • 2,982
  • 27
  • 32
6

I ended up with

price = price.round(precision)
price = price % 1 == 0 ? price.to_i : price.to_f

this way you even get numbers instead of strings

Eugene
  • 991
  • 10
  • 10
3

Here's another way:

decimal_precision = 2
"%.#{x.truncate.to_s.size + decimal_precision}g" % x

Or as a nice one-liner:

"%.#{x.truncate.to_s.size + 2}g" % x
alexebird
  • 63
  • 1
  • 4
3

I just came across this, the fix above didnt work, but I came up with this, which works for me:

def format_data(data_element)
    # if the number is an in, dont show trailing zeros
    if data_element.to_i == data_element
         return "%i" % data_element
    else
    # otherwise show 2 decimals
        return "%.2f" % data_element
    end
end
Joelio
  • 4,621
  • 6
  • 44
  • 80
2

Easy with Rails: http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_with_precision

number_with_precision(value, precision: 2, significant: false, strip_insignificant_zeros: true)
Yarin
  • 173,523
  • 149
  • 402
  • 512
-2

I was looking for a function to truncate (not approximate) a float or decimal number in Ruby on Rails, I figure out the follow solution to do that:

you guys can try in your console, the example:

>> a=8.88
>> (Integer(a*10))*0.10
>> 8.8

I hope it helps somebody. :-)