'Number of sigfigs to make difference significant

I am looking for an algorithm for the following (which may not be entirely well-formed, it's not yet clear in my head):

Let n1 and n2 be two double-precision floating point values. What is the smallest number of sigfigs (base 10) such that the difference n1 - n2 is significant relative to n1 and n2?

I suspect this has a well known solution but I have no background in significance arithmetic. Nevertheless here's my attempt:

  • If the result is significant for the larger (in magnitude) value, it is also significant for the smaller; so we can just use the larger value. Call it n.
  • Compute the most significant place value via floor(log10(n)). For example for the value 123.45 this would be 3, the hundreds place. Do the same for the delta.
  • The answer is the difference in these place values, plus 1; but never less than 1.

For example, consider 5000 - 4990. Here the difference is 10, which is significant if 5000 has three or more sigfigs. 5000 has place value 4, and the difference 10 has place value 2; thus the answer is 4 - 2 + 1 = 3.

Some C code for my attempt

// \return the value X such that n1 should be considered equal to n2 whenever sigfigs is less than X.
int deltaSigFigs(double n1, double n2) {
  if (n1 == n2 || (isnan(n1) && isnan(n2))) {
    return INT_MAX;
  } else if (!isfinite(n1) || !isfinite(n2)) {
    // Handled the case of Inf == Inf and -Inf == -Inf above.
    return 0;
  }

  double delta = fabs(n1 - n2);

  // Find absolute value of larger-in-magnitude number.
  double abig = fmax(fabs(n1), fabs(n2));
  
  // Say N is represented as m * 10^e (m possibly negative).
  // Then the number of sigfigs is the difference in exponents
  // between the largest in magnitude, and the delta.
  double exp = floor(log10(abig));
  double expDelta = floor(log10(delta));

  // expDelta may be larger than exp, for example deltaSigFigs(8, -8) computes a delta of 16.
  // Never return less than 1.
  if (expDelta > exp) return 1;
  return (int)exp - (int)expDelta + 1;
}

Thank you for any help!



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source