7

Is there a way in Python to count the significant figures in a double/float/etc? I'm not seeing an easy way to do this, but I'd expect it to be in the library.

Thanks in advance.

user456584
  • 86,427
  • 15
  • 75
  • 107
  • 5
    A number doesn't intrinsically *have* a number of significant figures, You specify how many significant figures you want to display *for* a number. Is that what you're asking to do? – tjm Nov 12 '11 at 00:04
  • 1
    How are you defining 'significant figures'? – johnsyweb Nov 12 '11 at 00:13
  • @tjm a number does intrinsically have significant figures. The number of significant figures communicates the accuracy of your measurement. See http://en.wikipedia.org/wiki/Significant_figures#Identifying_significant_digits – Will Nov 12 '11 at 01:55
  • @Will, I've got to disagree. Point three at your link, for example, states: "Trailing zeros in a number containing a decimal point are significant." Well just armed with that, take the representations, 2.25, 2.250, and 2.2500000. The number in each case is 2 and a quarter, but they have, 3, 4, and 8 significant digits respectively. So, what is the intrinsic number of significant digits for the number 2 and a quarter? – tjm Nov 12 '11 at 02:04
  • @tjm Ah, I see your point. I misinterpreted your statement. Any sig fig finding function would definitely have to take a string representation of a number as input. – Will Nov 12 '11 at 02:10
  • Similar [question](http://stackoverflow.com/questions/8142676/python-counting-significant-digits) for counting sig figs. – The Demz Oct 07 '12 at 12:02

6 Answers6

3

I found a solution to this post in another question:

Python counting significant digits

The idea here is that you pass the float as a String to the methods, and then the method uses regular expressions to count the number of significant digits by splitting strings where "e" is (for float string in scientific format) and where the dot is (for normal float strings).

It seems to work well up to 8 significant digits, but the behavior is not guaranteed after the 9th.

Still, I believe this is better than the

"Significant digits are just not that big a deal and get little support in computer languages"

response. It may not be easy, but you can definitely do it, even if not perfectly.

Community
  • 1
  • 1
Flame_Phoenix
  • 16,489
  • 37
  • 131
  • 266
3

You may be interested in an arbitrary precision floating point library such as this one:

http://code.google.com/p/mpmath/

Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
2

The built-in Decimal library can help out pretty well with this since it gets around concerns with using hardware-based floating point numbers. It has an internal representation that just contains the significant digits and the exponent. So you can use that to count significant figures like this:

from decimal import Decimal
def count_sigfigs(numstr):
    return len(Decimal(numstr).normalize().as_tuple().digits)
 

This works pretty well for lots of examples, like these ones (from this related question). Note that you do have to input the numbers as strings for it to work right. Using floats would mess it up because of their hardware representation.

tests = [('2', 1),
 ('1234', 4),
 ('2.34', 3),
 ('3000', 1),
 ('0.0034', 2),
 ('120.5e50', 4),
 ('1120.5e+50', 5),
 ('120.52e-50', 5)]

for num, expected in tests:
    print(count_sigfigs(num) == expected)

Which gives:

True
True
True
True
True
True
True
True

Unfortunately this does not quite work on numbers like "1.000" which have 4 sigfigs. This just gives 1. So it'd need improvement to cover all cases. Also it gives 1 for "0" though that typically should give 0.

If you take out the normalize then it works for 1.000 but not for 3000 (it says 4 rather than 1).

partofthething
  • 1,071
  • 1
  • 14
  • 19
  • It only took 10 years to get a useful answer to this question. I tried it out and it worked for my purposes. – jjet Feb 24 '22 at 17:38
2

No. Significant digits are just not that big a deal and get little support in computer languages. People doing real computations need error bars, which have far more precision — real measurements say very exact things like “this is 0.11 ± 0.03mm“ instead of saying either of the less exact statements “this is 0.1 mm” or “this is 0.11 mm” which makes you choose a power of ten even if your inexactness does not actually fall at a power of ten.

Brandon Rhodes
  • 83,755
  • 16
  • 106
  • 147
  • 3
    Significant figures are extremely important, and are necessary to track the accuracy of measurements, even with error bars. There are several famous cases where ignoring significant figures has lead to incorrect results. – Will Nov 12 '11 at 01:53
  • Significant figures are very important to school children because they are easy to use — but in “significant-figure-speak,” the measure 0.10 means “0.10 ± 0.01” and 0.100 means “0.100 ± 0.001.” My point is that significant figures are a simplification of the more general concept of measurement error, and therefore that scientific math libraries are going to support error, not significant figures. Because, as I hinted in my answer, error tends to have all sorts of values, and rarely happens to land right on a power of ten. :) – Brandon Rhodes Nov 12 '11 at 01:58
  • 1
    Don't come down so hard on sig figs, they're important to others aside from school children. Physicists, for example, use them all the time when the accuracy of measurement error isn't so important. – Will Nov 12 '11 at 02:09
  • 2
    You're right — I should have said “important when doing work by hand, or informally before preparing the math for actual publication” — and I would go back and adjust my “school children” wording if not for the fact that 31 minutes have passed and the commend is un-editable. *sigh* – Brandon Rhodes Nov 12 '11 at 02:31
  • You still need to count sig figs to present your uncertainty. In your example, you adjusted the number of digits of 0.11 to the number of digits of the error. – Jérémy Talbot-Pâquet Jul 05 '22 at 19:03
1

Computers simply don't work that way, at least, not unless they are programmed to do so. The assumption is the number you give them is exact. If you create the number 2/3 as 0.6666666666666667, then all operations treat it as exactly that. That error in the least significant digit may end up propagating to larger errors in later computations, but this is something that good code should deal with, using algorithms that minimize these issues when possible.

As I said however, computers do what they are told to do. So there are packages written that use what is called interval arithmetic. A number may then be described as an interval, so we might create 2/3 as the interval [0.6666666666666666,0.6666666666666667]. We can operate on intervals, adding, subtracting, multiplying, etc. Those operations will often see interval widths expand as we operate with them.

The fact is however, even if you use interval arithmetic tools, it is YOU who must know at the beginning the number of significant digits in your numbers. If you create a number as 2.2, storing it as a double, then the computer will actually try to store the number as 2.200000000000000, and assume that all the digits are exactly correct. In fact of course, because floating point arithmetic is employed, the number will actually be stored internally as a binary number. So 2.2 will probably be effectively stored as the number:

2.20000000000000017763568394002504646778106689453125

because most decimal fractional numbers are not representable exactly in binary form. Again, care must be employed in all software, but also always by the person who is using those tools to understand what their numbers really mean.

This last point is important. Many people treat the numbers generated by a computer as truth, as handed down by the computer god on a stone tablet. If the computer prints out 1.4523656535725, they believe every digit of what they see. In fact, common sense must be applied here, to know that perhaps this number was generated from data that had only 3 significant digits, so that you may choose to rely on only the first few significant digits of that number. And of course, this is why you are taught about that concept in school, to know what to trust, and what not to trust. Remember however - computers will generally be infinitely trusting. It is you who must apply the filter.

0

I used the formatters to do it. Here's an example with a measurement a and an error a_error.

a = 0.0595269489794585
a_error = 0.00089489789798
sig_fig_pos = abs(int(f'{G_err:e}'.split('e')[-1]))
a = float(f'{a:.{sig_fig_pos }f}')
a_error = float(f'{a_error:.{sig_fig_pos }f}')
print(a, '±', a_error)

Will adjust the number of sig figs

0.0595 ± 0.0009