-1

I want to round values to three significant digits. I want to get answers as follows:

39.07 -> 39.1
9.0712 -> 9.07
9.0071-> 9.01
0.01523 -> 0.0152
0.00150 -> 0.0015
39.01233 -> 39

If there are more than three significant figures before the decimal point, all figures before the decimal point should be displayed:

11327 -> 11327
11327.314 -> 11327
11327.84 -> 11328
sawa
  • 165,429
  • 45
  • 277
  • 381
Kalpa-W
  • 348
  • 3
  • 22
  • mudsie (aka @Aleksei), perhaps so, but it has been [asked before](https://stackoverflow.com/questions/8382619/how-do-i-round-a-float-to-a-specified-number-of-significant-digits-in-ruby). – Cary Swoveland Oct 12 '18 at 05:42
  • 1
    I don't think this is off-topic. But should be more constructive. Please refer the following link to know "How to ask a good question" https://stackoverflow.com/help/how-to-ask – codebot Oct 12 '18 at 06:51
  • So, `0.0000000000150` should become `0.000000000015`? – Kimmo Lehto Oct 12 '18 at 07:47

1 Answers1

5
class Float
  def signif(signs)
    Float("%.#{signs}g" % self)
  end
end

> (39.07).signif(3) #=> 39.1
> (9.0712).signif(3) #=> 9.07 
> (9.0071).signif(3) #=> 9.01
> (0.01523).signif(3) #=> 0.0152 
> (0.00150).signif(3) #=> 0.0015 
> (39.01233).signif(3) #=> 39.0 

OR

> require 'bigdecimal'
> BigDecimal.new(39.07, 3).to_f #=> 39.1
> BigDecimal.new(9.0712, 3).to_f #=> 9.07 
> BigDecimal.new(9.0071, 3).to_f #=> 9.01
> BigDecimal.new(0.01523, 3).to_f #=> 0.0152 
> BigDecimal.new(0.00150, 3).to_f #=> 0.0015 
> BigDecimal.new(39.01233, 3).to_f #=> 39.0

UPDATE:

As above solution is not supporting more than three significant figures before the decimal point. so I have taken significant dynamically, now you can pass any big numbers. no need to pass significant. As per Cary Swoveland's comment if the value is equal as Integer version, should return Integer value instead Float.

class Float
  def dynamic_signif
    f = Float("%.#{self.to_i.to_s.size}g" % self)
    n = (f==f.to_i) ? f.to_i : f
  end
end  

> (11327.314).dynamic_signif #=> 11327
> (11327.84).dynamic_signif #=> 11328

NOTE: As this method belongs to Float class, so it won't work for FixNum, you may need to convert Fixnum to Float.

Gagan Gami
  • 10,121
  • 1
  • 29
  • 55
  • Hi Gagan, Thank you very much for your answer. it is working for the given examples. But this method is not supported for the followings. right? 11327.314 -> 11327 (If there are more than three significant figures before the decimal point, all figures before the decimal point should be displayed. This need to be considered for Three significant figures) – Kalpa-W Oct 12 '18 at 05:17
  • @Kalpa-W in that case you need to use significant as `5` here it's output `BigDecimal.new(11327.314, 5).to_f => 11327.0` – Gagan Gami Oct 12 '18 at 05:20
  • @Kalpa-W : I have updated my answer, you don't need to pass significant, it will work for any significant figures before the decimal point. – Gagan Gami Oct 12 '18 at 05:26