2

I'm looking for, a hopefully simple way to find, the least significant digit in a number (float or integer).

For example:

101 --> 1

101.2 --> 0.2

1.1003 --> 0.0003

Cases like 10, 100, 1000 etc are slightly less relevant, though I'd be interested regardless.

I don't particularly care about the format so if it makes more sense to identify the result in a more practical manner feel free.

For example:

101.2 --> 0.1 or 10^-1 (or even -1 for the relevant power/exponent) is fine.

For additional context, what I am trying to do:

Lets say I have a number 31.6 I want to be able to turn that in into 31.5 (decrease the least significant digit by 1). Lets say I have the number 16, I want to turn that into 15 (same idea). If I have the number 100, I still want to turn that into 99 but I can probably figure out the case handling there (without specifying 100.0, I think the 1 is the least significant digit and decreasing by 1 gives you 0, which is not what I want). This in turn is related to manually manipulating class breaks in data ranges (going off topic though).

Showing my homework: This looks promising (the leastSigDigit part), but it returns the digit without any (mathematical) reference to the power of the digit (and I'm hoping to avoid lots of string conversions too).

This was what came up when I searched stackoverflow but doesn't seem helpful (if I'm using the wrong terminology/search phrases my apologies in advance)

Community
  • 1
  • 1
Richard W
  • 322
  • 3
  • 13
  • 2
    What should the output be for an approximation of `3.5` that really is `3.5000000000000000000000001`? – Andrew Johnson Aug 29 '14 at 15:18
  • For ints, this isn't too bad (use `%10` and `/=10` as appropriate). For floats, this may be impossible: if `.1` gets converted to `.0999999999`, your answer radically changes. I don't understand your example `101.2 -> 0.1`; is that a typo? – Teepeemm Aug 29 '14 at 15:20
  • If you need specific decimal rounding behavior, you might want the [`decimal`](https://docs.python.org/2/library/decimal.html) module. – user2357112 Aug 29 '14 at 15:21
  • @Andrew Johnson I hadn't thought about that/usually don't need to worry about that. Without reading up more on the particulars I'm assuming '1.1 + 2.2' = 3.3 instead of 3.3000000000000003, in case that impacts things. – Richard W Aug 29 '14 at 15:32
  • 1
    That's a bad assumption to make, since the rounding could result in a number that's too small instead of too large. (For example, on my machine 1.2 + 2.4 is 3.5999999999999996.) – chepner Aug 29 '14 at 15:35
  • @Teepeemm, regarding the 101.2 --> 0.1, this is effectively returning the power (precision?) of the relevant digit (I'm assuming I can find the value of the digit if I know what position to look for it in). 0.1 = 10^-1, which is the relevant exponent version. – Richard W Aug 29 '14 at 15:36

1 Answers1

7

If you already have floats, this isn't going to work. Python floats don't carry the information you need. There's no distinction between 1. and 1.0, and if you divide a 1.0 and a 3.0, you get 0.3333333333333333 (except it's really 0.333333333333333314829616256247390992939472198486328125).

If your inputs are strings, you can do it pretty easily:

def least_significant_digit_power(num_string):
    if '.' in num_string:
        # There's a decimal point. Figure out how many digits are to the right
        # of the decimal point and negate that.
        return -len(num_string.partition('.')[2])
    else:
        # No decimal point. Count trailing zeros.
        return len(num_string) - len(num_string.rstrip('0'))
user2357112
  • 260,549
  • 28
  • 431
  • 505