Title: Display significant digits in C#
The number of significant digits in a number is the number of digits that carry meaningful information. These include all of the digits displayed except leading and trailing zeros. A decimal point and trailing zeros after the decimal point imply that the digits before them are significant.
For example, the value 12,000 has 2 significant digits: the 1 and 2. What this intuitively means is that the value is 12,000 to the nearest 1,000.
In contrast, the value 12,000.0 has 6 significant digits. The 0 after the decimal point implies that it and the digits before it are significant.
There are a few murky areas. For example, suppose you actually know the value 12,000 to the nearest 100. How can you represent that? The only two ways I know to handle this are to make a note of the fact or to use scientific notation. The trailing 0 in the coefficient of 1.230e4 implies that it is a significant digit.
This example uses the following extension method to convert a double value into a string with a specified number of significant digits.
// Format the value with the indicated number of significant digits.
public static string ToSignificantDigits(
this double value, int significant_digits)
{
// Use G format to get significant digits.
// Then convert to double and use F format.
string format1 = "{0:G" + significant_digits.ToString() + "}";
string result = Convert.ToDouble(
String.Format(format1, value)).ToString("F99");
// Rmove trailing 0s.
result = result.TrimEnd('0');
// Rmove the decimal point and leading 0s,
// leaving just the digits.
string test = result.Replace(".", "").TrimStart('0');
// See if we have enough significant digits.
if (significant_digits > test.Length)
{
// Add trailing 0s.
result += new string('0', significant_digits - test.Length);
}
else
{
// See if we should remove the trailing decimal point.
if ((significant_digits < test.Length) &&
result.EndsWith("."))
result = result.Substring(0, result.Length - 1);
}
return result;
}
The code composes a format string of the form {0:G4} where 4 is the desired number of significant digits. The code then passes that format specifier to the String.Format method to get the double value formatted with the correct number of significant digits.
The G format specifier gives the desired number of significant digits but it does not include trailing 0s and it may use scientific notation if that produces a shorter result.
To fix those problems, the code uses Convert.ToDouble to convert the resulting string back into a double. It then uses the F99 format to convert the double into a fixed-point string (not scientific notation) with 99 digits (the longest string that the format can produce). The code then trims off the trailing 0s.
At this point, the result looks like the correct value but it may not have the right number of significant digits if trailing 0s are required. To add trailing 0s, it makes a test string and removes its decimal point and leading and trailing 0s to leave just the significant digits present. The code subtracts the length of this string from the number of significant digits required and adds trailing 0s to the final result if necessary.
The following code shows how the program uses the extension method.
double number = double.Parse(txtNumber.Text);
int num_digits = (int)nudDigits.Value;
txtResult.Text = number.ToSignificantDigits(num_digits);
string format = "{0:G" + num_digits.ToString() + "}";
txtGFormat.Text = String.Format(format, number);
The code gets the number and the number of significant digits. It then calls the number's ToSignificantDigits method to format the value. The code also displays the result of the G format so you can see the difference.
Displaying significant digits seems like it should be a simple concept, but it's surprisingly hard to do. You may want to step through a couple of examples in the debugger to see exactly how it works. It would also be nice if the Framework's formatting classes included this feature.
This also explain how you find the number of significant digits in a calculation. For example, consider the expression 8 × 8.0. The value 8 has one significant digit but the value 8.0 has two significant digits. When you multiply the two values, the result is 64, but that value implies that the result has two digits of precision. Because the value 8 has only one significant digit, the result can have only one significant digit so the correct result is 60.
For more information on finding significant digits in calculations, see this Wikipedia article.
Download the example to experiment with it and to see additional details.
|