<p>When working with engineering data, it is often important to know the number of <a href="https://en.wikipedia.org/wiki/Significant_figures" rel="nofollow noreferrer">significant digits</a> of numbers. However, decimal numbers in languages I've encountered so far don't seem to include this concept. They just specify the <em>maximum</em> number of significant digits and pad every value to match that. See for example <a href="https://www.db-fiddle.com/f/4jyoMCicNSZpjMt4jFYoz5/8732" rel="nofollow noreferrer">PostgreSQL</a>, <a href="https://www.online-python.com/gGDITRL9dk" rel="nofollow noreferrer">Python</a>. Are decimal numbers with significant digits implemented in any mainstream languages, and if so, how?</p>
<p>As a side note, if I understand correctly the difference between decimals with and without embedded information about significant digits is analogous to the difference between <a href="https://en.wikipedia.org/wiki/Unum_(number_format)#Valid" rel="nofollow noreferrer">valids</a> (Type III Unums/Posits with built-in support for range arithmetic) and floating point.</p>

<numbers>
How are significant digits implemented?
CC BY-SA 4.0
2023-05-20T23:01:28.577Z
COBOL and I think some SQL dialects have decimal fixpoint numbers.
Gilles 'SO- stop being evil'
CC BY-SA 4.0
2023-05-21T03:33:52.160Z
@Gilles'SO-stopbeingevil'  Decimal fixpoint numbers, per se, are not OP's concern apparently, as they typically have a static number of digits, with no provision for tracking the dynamic number of significant digits, which is data driven, requiring a compound structure to record that characteristic as well as the data value.  Additionally, it presumably can do arithmetic with such data types, which requires special handling for [significance calculation](https://en.wikipedia.org/wiki/Significance_arithmetic) as well as value calculaiton.
mgkrebbs
CC BY-SA 4.0
2023-05-22T00:59:13.980Z
@mgkrebbs Exactly. Also, interesting article!
l0b0
CC BY-SA 4.0
2023-06-21T18:40:47.093Z
In science, you generally don't use significant digits to determine the precision. You calculate the error ranges using partial derivatives.
FlatAssembler
<p>Those languages that <em>do</em> provide significant digits do so more for accounting purposes than for scientific accuracy.
For instance, COBOL has &quot;PIC 99999v99&quot; to define a 7-digit value with 2 digits after the decimal place.
But this is generally used to keep track of the exact number of cents within a dollar, with no concept of partial cents, not used to track scientific accuracy.</p>
<p><code>99999v99</code> doesn't mean that the value is stored with 7 significant digits.
It means that the value being tracked is precise and will never have more than 7 significant digits; if more decimal places were added they would always be zero.</p>
<p>For engineers, significant digits are only a convenient approximation of what really should be tracked.
It provides a crude value suitable for quick back-of-envelope calculations, but should not be used when better methods are available.</p>
<p>For instance, the numbers <code>1</code> and <code>9</code> each have one significant digit, meaning the true value is within ±½.
That means that the first value is somewhere between .5 and 1.5 and the second between 8.5 and 9.5.
That's ±50% error for the first but less than ±6% error for the second.</p>
<p>Whether as part of the language itself, or as a class implementation, for scientific precision, rather than storing a value and a number of digits, the basic type should store two numbers defining the range of possible values for a number.
E.g:</p>
<pre><code> value = (3.141, 3.142)
 2 * value ⇒ (6.242, 6.284)
 value² ⇒ (9.865881, 9.872164)
 value + value² ⇒ (16.107881, 16.156164)
</code></pre>
<p>In cases where one <em>does</em> care about significant digits, that can easily be determined by the range values.<br />
(E.g. the last example differs in the 4th digit, so it can be said to have 3 significant digits.)</p>

CC BY-SA 4.0
2023-05-22T12:44:23.937Z
2023-05-22T12:51:29.993Z
2023-05-22T12:51:29.993Z
Ray Butterworth
CC BY-SA 4.0
2023-05-22T13:17:04.813Z
The issue with interval arithmetic like this is that, if done compositionally, it's pessimistic ─ for example if we know that `x` is in the range (1.5, 1.6), then `x²` will be in the range (2.25, 2.56) and then `x² - x` will be in the range (0.625, 1.06) because it could be as small as `2.25 - 1.6` or as large as `2.56 - 1.5`. But the terms `x²` and `x` aren't independent, and the actual range of mathematically possible results is (0.75, 0.96). After more computations, the conservative range of possible values grows exponentially larger than the actual range. So this doesn't tend to be useful.
kaya3
CC BY-SA 4.0
2023-05-22T20:53:28.703Z
This doesn't answer how it's implemented, but only vaguely how interval arithmetic could work at a surface level. Good point though, that there are better ways to do accuracy-preserving calculations than just significant digits.
l0b0
CC BY-SA 4.0
2023-05-22T20:54:59.563Z
@kaya3 In science, you generally *don't* want to exaggerate the accuracy of any numbers. Using interval arithmetic discourages researchers from massaging the data too much before presenting it, which IMO is a useful feature.
l0b0
# How are significant digits implemented?
Posted by: username_0 on 2023-05-20
When working with engineering data, it is often important to know the number of [significant digits](https://en.wikipedia.org/wiki/Significant_figures) of numbers. However, decimal numbers in languages I've encountered so far don't seem to include this concept. They just specify the *maximum* number of significant digits and pad every value to match that. See for example [PostgreSQL](https://www.db-fiddle.com/f/4jyoMCicNSZpjMt4jFYoz5/8732), [Python](https://www.online-python.com/gGDITRL9dk). Are decimal numbers with significant digits implemented in any mainstream languages, and if so, how?

As a side note, if I understand correctly the difference between decimals with and without embedded information about significant digits is analogous to the difference between [valids](https://en.wikipedia.org/wiki/Unum_(number_format)#Valid) (Type III Unums/Posits with built-in support for range arithmetic) and floating point.
**Tags:** numbers
> **Comments:**
> **username_1**: COBOL and I think some SQL dialects have decimal fixpoint numbers.  
> **username_2**: @Gilles'SO-stopbeingevil'  Decimal fixpoint numbers, per se, are not OP's concern apparently, as they typically have a static number of digits, with no provision for tracking the dynamic number of significant digits, which is data driven, requiring a compound structure to record that characteristic as well as the data value.  Additionally, it presumably can do arithmetic with such data types, which requires special handling for [significance calculation](https://en.wikipedia.org/wiki/Significance_arithmetic) as well as value calculaiton.  
> **username_0**: @mgkrebbs Exactly. Also, interesting article!  
> **username_3**: In science, you generally don't use significant digits to determine the precision. You calculate the error ranges using partial derivatives.  
---
## 1 answers
### Answer by username_4 on 2023-05-22. Score: 3
Those languages that do provide significant digits do so more for accounting purposes than for scientific accuracy.
For instance, COBOL has "PIC 99999v99" to define a 7-digit value with 2 digits after the decimal place.
But this is generally used to keep track of the exact number of cents within a dollar, with no concept of partial cents, not used to track scientific accuracy.
99999v99 doesn't mean that the value is stored with 7 significant digits.
It means that the value being tracked is precise and will never have more than 7 significant digits; if more decimal places were added they would always be zero.
For engineers, significant digits are only a convenient approximation of what really should be tracked.
It provides a crude value suitable for quick back-of-envelope calculations, but should not be used when better methods are available.
For instance, the numbers 1 and 9 each have one significant digit, meaning the true value is within ±½.
That means that the first value is somewhere between .5 and 1.5 and the second between 8.5 and 9.5.
That's ±50% error for the first but less than ±6% error for the second.
Whether as part of the language itself, or as a class implementation, for scientific precision, rather than storing a value and a number of digits, the basic type should store two numbers defining the range of possible values for a number.
E.g:
 value = (3.141, 3.142)
 2 * value ⇒ (6.242, 6.284)
 value² ⇒ (9.865881, 9.872164)
 value + value² ⇒ (16.107881, 16.156164)

In cases where one does care about significant digits, that can easily be determined by the range values.
(E.g. the last example differs in the 4th digit, so it can be said to have 3 significant digits.)
> **Comments:**
> **username_5** (2023-05-22): The issue with interval arithmetic like this is that, if done compositionally, it's pessimistic ─ for example if we know that `x` is in the range (1.5, 1.6), then `x²` will be in the range (2.25, 2.56) and then `x² - x` will be in the range (0.625, 1.06) because it could be as small as `2.25 - 1.6` or as large as `2.56 - 1.5`. But the terms `x²` and `x` aren't independent, and the actual range of mathematically possible results is (0.75, 0.96). After more computations, the conservative range of possible values grows exponentially larger than the actual range. So this doesn't tend to be useful.  
> **username_0** (2023-05-22): This doesn't answer how it's implemented, but only vaguely how interval arithmetic could work at a surface level. Good point though, that there are better ways to do accuracy-preserving calculations than just significant digits.  
> **username_0** (2023-05-22): @kaya3 In science, you generally *don't* want to exaggerate the accuracy of any numbers. Using interval arithmetic discourages researchers from massaging the data too much before presenting it, which IMO is a useful feature.  
---
