class Float

Public Instance Methods

signif(num_digits) click to toggle source

Two cases : self.abs >= 1, and self.abs < 1 If >= 1, we can use .round(), adjusting for the number of digits before the decimal point If < 1, .round() will not ignore leading zeroes, so we have to use another means There is another complication in that 0.00000766.to_s returns 7.66e-06 , not 0.00000766 as we would prefer here

# File lib/more_ruby/float.rb, line 9
def signif(num_digits)
    raise TypeError, "Must call #{__method__} with an Integer" unless num_digits.kind_of?(Integer)
    raise ArgumentError, "Must call #{__method__} with a positive Integer" if num_digits < 0 # 0 is a special case, but allowed
    # Special cases
    return 0.0 if num_digits == 0
    return self if self == 0.0

    negative = self < 0 # remember its sign for later

    # Need to check to see if the numebr is small enough that to_s will put it into scientific notation
    if self.to_s =~ /^(\d)\.(\d*)e-(\d+)$/
        places = 1 + $2.size + $3.to_i             
        s = "%.#{places}f" % self # should print out 7.66e-06 as 0.00000766
    else
        s = self.to_s
    end
    parts = s.split(".")
    whole = parts[0].to_i.abs

    # significant figures ignore leading zeroes, so we can only return early here if self.abs > 1
    # 123.456.signif(4) should return 123.4; 123.456.signif(3) should return 123
    if whole != 0 # equivalent to self.abs > 1
        if num_digits <= whole.digit_count
            return whole.signif(num_digits).to_f 
        else
            return self.round(num_digits - whole.digit_count)
        end
    end

    fraction_as_s = parts[1] # keep as string for now
    return whole.signif(num_digits).to_f unless fraction_as_s # should not be possible, but check it anyway
    return whole.signif(num_digits).to_f if fraction_as_s == "0"

    relevant_fraction_digits = num_digits
    fraction = "0.#{fraction_as_s}".to_f
    fraction_as_s =~ /^([0]*)[1-9]/
    leading_zeroes_count = $1.size
    rounded_fraction = fraction.round(relevant_fraction_digits + leading_zeroes_count)
    if negative
        return -(rounded_fraction)
    else
        return rounded_fraction
    end
end