Significant digits in different number systems

I’m playing around in programming, and one of the projects that I want to do is a function that converts numbers between different number systems. I also want it to be able to handle floating point fractions. That made me wonder how the concept of significant digits comes into play when converting numbers between systems.

Obviously, a number that is very easy in one system can be an infinite series in another. For example, the fraction one third is an infinite series in decimal (0.333333…), but in base-6 it becomes a very handy 0.2. Conversely, the fraction one fifth is easy in decimal (0.2), but an infinite series in base-6 (0.1111111…).

I wonder what consequences that has for my number conversion function, which I want to be mathematically sound. Suppose I get the input 0.2 in decimal, and I want to convert it into base-6. Would it be sound to return 0.1, arguing that the input had one significant digit after the point and that therefore the output would have the same, cutting off the 0.11111… after the first 1 after the point?

No. Simple as that really. Significant figures is a way of expressing error, and is really shorthand for the complete understanding of the error. You are not carrying any additional error estimate information in your number system, so any notion of significant figures isn’t possible. (A system that does carry errors can be built, and is an interesting idea in and of itself, but isn’t what you are doing.)
The intrinsic error in a floating point number is in truncation of the least significant bit, not in the sudden appearance of a perfectly representable number versus one that requires a continued fraction in that base.

Unless you know otherwise (that is have an error bound) 0.2 does not have just one significant figure. It as as many significant figures are your representation allows right of the decimal point. It is coincidence they are all 0. But zero is just as good a digit as any other.

If I’m following this right @Francis_Vaughan, you are pointing out that just because the display spits out 0.2, it doesn’t mean that you have a number with 1 significant figure - in fact you have 0.2000000… etc, to whatever maximum number of figures the program can handle?

Yup. That is the nub of it.
Significant figures isn’t a count of how many figures there are, it is a count of how many figures are meaningful. Those zeros are meaningful.

As a display, or as the actual number returned and held in memory?

As a display, I’d say probably not, unless there is a reason you want only one significant digit past the decimal, but that’s cosmetic.

As the actual number returned and held in memory, I’d say absolutely not. If nothing else, what happens if you want to convert back to base 10? You won’t get .2 back. (Hmm, well, I guess you would if you kept rounding the same way, as you would get back .1666… which would round up to .2, but that’s pretty sloppy and not reliable.)

This is a bit off topic from my project, but it’s interesting nonetheless. Suppose I have a data point that’s simply given as 0.2. How would I (or the number system in use) know that it’s in fact 0.2000000…, i.e. one fifth exactly, rather than 0.2xyyyyyyyy (with x representing a digit from 0 to 4, and the ys representing any digit), cut off to one significant figure?

It could be both. My idea is to have a function that can convert from any number system (well, any up to base-36 - the characters would be the ten digits plus the 26 letters of the alphabet) to any other. If both the target and the source system are not decimal, then I’d use decimal as an intermediate system: The number gets converted by one sub-function into decimal, and the by another sub-function from decimal into the target system. So if the representation of the number into decimal is an infinite series, then it’d be held in a truncated form in memory for further processing. If, on the other hand, the number is handy in decimal (like my 0.2 in decimal), then it can still turn out to be infinite, and get truncated, when converted from decimal into the target system (like my 0.11111… in base-6).

So suppose I were to convert 0.4 from base-20 to base-6. It’s handy in the source system and also in the intermediate decimal system (where it becomes 0.2), but then becomes 0.111111… in the target system (base-6). So that’d be a case where it’s displayed in a truncated form (perhaps not truncated to one digit after the point, maybe something like five or six). If, on the other hand, the job is to convert 0.2 in base-12 to base-6, then I get 0.166666… in decimal, which would get truncated before conversion into base-6 (where it should be 0.1 exactly - but I suppose after the truncation in decimal, it won’t be).

That depends on how your data is presented. If some points are presented as 0.20, while others are presented as 0.2 , then you might be able to conclude that the number of digits presented is an indicator of precision. But if it’s 0.18 , 0.19, 0.2 , 0.21 , 0.22 …, then it just means that the presentation of the digits is automatically truncating trailing digits.

In any event, even when done right, significant digits are just a quick-and-dirty way of representing precision an error estimates. You can’t distinguish, using significant digits alone, between a number that’s meant to be 2 ± 0.2 and one that’s meant to be 2 ± 0.3 . And if you’re going to be going to the trouble of making a computer arithmetic system that tracks error estimates, then you ought to just go all the way and do it right, with (at least) a separate number indicating standard deviation attached to every value, and proper error propagation of those values. Or better yet, a representation of a full error distribution, though that can take a lot more data.

Why on Earth would you do this? Extra conversions don’t do anyone any good.

I suspect that you’re thinking in terms of “a base-n number” and “a number” as being separate things, and defaulting to thinking of “a number” as meaning “a base-10 number”. But all bases are equally valid, and many bases are more convenient than 10.

Especially since all of this is actually going to be done in base 2 by the computer.

It started like this because I had some practice converting numbers to and from base-10 manually, so it was easier for me to come up with the algorithm to do this. But I understand that any number representation is just as good as any other, so I guess it will, after all, be better to have a generalised version of my algorithm that deals directly with the powers of the bases, rather than powers of ten.

Numbers that represent real measurements of non-discrete/continuous things (e.g. time, distance) will have three components, ideally:

  1. The measurand itself, e.g. 5.234 inches.

  2. The uncertainty of the measurand, e.g. ±0.0015 inches.

  3. The confidence interval, e.g. 95%.

That would be two things for each number, not three, because the confidence interval you choose should be consistent across your entire system. And you’re probably best off choosing a confidence interval that corresponds to the standard deviation.

My understanding is that usual floating-point arithmetic is performed using a fixed number of significant digits. E.g., double precision binary has 53 digits.

Interval arithmetic is something else.

It appears to me that there are two entirely distinct concepts of “significant digits” being discussed here. The first, as discussed by Schnitte, DPKR, et al, concerns truncation of digits when mathematical operations are performed numerically. The second, as discussed by Crafter_Man, Chronos, et al concerns the uncertainties associated with measured values. I think that each of these two concepts merit discussion but discussing both at the same time might lead to confusion.

Personally, I almost always think of significant digits in terms of uncertainties of measured values, but that is just because of what I do at work in my current job. I am aware of truncation in numerical analyses but that rarely affects me as my calculators/computers can generate way more digits than I will ever have need for.

In my opinion, sometimes the concept of significant digits is entirely inapplicable. For example, when discussing the natural number 347 or the rational number 1/213, why would you even talk about significant digits?

I really like the distinction you’re making here between “how many figures can I count on?” (precision of an output) and “how many figures do I need for an output I can count on? (precision of an input and/or process).

For example, I do finite element analysis for work, and that typically requires 64-bit floating points for adequate precision in the solving process. Inputs for static structural analysis typically require much less precision, depending on the scale. It doesn’t much matter whether your input load is 5.01 Newtons or 5.02 Newtons, but it would matter a lot if it were 0.01 N vs. 0.016 N.

Ultimately, the precision of the output depends on the precision of both the inputs and the subsequent mathematical operations. It seems to me that’s why it’s so easy to conflate some of these concepts.

Wouldnt it depend on why you’re discussing these numbers? One great reason to consider significant figures when discussing 347 is if it represented an angle in degrees and you wanted to operate in radians. Or if you wanted to store 1/213 as a decimal or binary number, you’d care about significant figures.

Maybe you’re talking about those numbers as “pure” numbers independent of any operation. But the latter number includes an operation as you represented it (in base 10), so I’m not sure what you mean here.

Yes, I was referring to “pure” numbers in my last paragraph. That is why I specified natural number and rational number and not measured quantities. The rational number 1/213 is a little inconvenient for this discussion so let’s discuss the rational number 1/7. 1/7 expressed as a decimal is 0.142857… where the sequence 142857 repeats an infinite number of times. (This would be better expressed by having a bar over the 142857. Does anybody know how to do that in this message board?) My calculator says that 1/7 is 0.1428571428571429. In my mind, 0.142857… and 0.1428571428571429 are two completely distinct different numbers. Nonetheless, I realize that sometimes 0.1428571428571429 might be close enough for the task at hand. But if you ask me how many significant digits are in the decimal expression of the “pure” number 1/7 my response might be something like, “What the heck are you talking about? If you are going to insist on answer then maybe we could say an infinite number of digits but why would anybody ask such a silly question?”

One warning for conversion functions: remember that the internal representation of a float is in binary, so any mantissa that is not a power of 2 will have a small rounding error. If you take a number and do repeated conversions, that rounding error will build up. For my project, it was converting between physics units, and included some logarithms so errors could build up pretty quick. When checking your code, take a number (your 1/6) convert it to another base then convert back, see how much error you’ve accumulated.

If you want most accurate results, instead of “start with .333333 repeating, convert to base 3 to get .1, convert .1 to base 5 to get ?, convert to base 16 to get???”, keep the original value in memory and always convertt from that. “Convert .3333 to base 3 and get .1, convert .3333 to base 5, convert .3333 to base 16”.

Small error at first, but those rounding errors can build up faster than you expect.

I think that, when talking about an integer or a rational as a “pure number”, you really need to specify in what context you’re dealing with it, because “pure” integers or rationals are really, really rare. Most of the time, when people are dealing with something that looks like integers, it’s just real numbers that are rounded to that degree.

There speaks a physicist. :grinning: