简体   繁体   English

浮点数:匹配多少位有效数字?

[英]Floating point: how many matching significant figures?

In C, Given two single or double precision floating point numbers, is there an easy way to determine how many of their significant figures "match"?在 C 中,给定两个单精度或双精度浮点数,是否有一种简单的方法可以确定它们的有效数字中有多少“匹配”? Ie if I have two such numbers with decimal representation 1.64298272 and 1.64298296 I would like to obtain the result 7 .即如果我有两个这样的十进制表示的数字1.642982721.64298296我想获得结果7 If I was concerned with decimal places this would be easy but I'm not sure how to go about it if I'm interested in significant figures.如果我关心小数位,这会很容易,但如果我对重要数字感兴趣,我不确定如何解决 go。

To do an exact compare, the value must be converted with sufficient precision.要进行精确比较,必须以足够的精度转换值。 DBL_DECIMAL_DIG (typical 17) is enough for double to make unique strings as suggested by @ryyker DBL_DECIMAL_DIG (典型值 17)足以让double生成@ryyker建议的唯一字符串

Form a string for both values为两个值形成一个字符串

//         -   d   .    digits - 1        e   -  expo \0
#define N (1 + 1 + 1  + DBL_DECIMAL_DIG + 1 + 1 + 5 + 1)
char buf[N + 10];  // Some extra too to cope with strange NaN payloads
// Consider changing round mode to "round towards 0.0.  See below notes.
snprintf(buf, sizeof buf,"%+.*e", DBL_DECIMAL_DIG - 1, value);

After testing for same sign and exponent, walk leading digits.在测试相同的符号和指数后,走前导数字。

Some sample hacked code.一些示例黑客代码。

if (buf1[0] != buf2[0]) return 0; // sign test
e1 = strchr(buf1, 'e');
e2 = strchr(buf1, 'e');
if (strcmp(e1,e2)) return 0; // expo test (non-finite concerns omitted here for brevity)
digit = 0;
s1 = buf1;
s2 = buf2;
while (s1 < e1 && s2 < e2) {
  if (isdigit(*s1)) {
    if (*s1 == *s1) digit++;
    else break;
  }
  s1++; s2++;
}
return digit;

If code attempts to do this without s*printf() , the math involved to examine a binary based floating-point number and convert to decimal for compare will effectively re-do what sprintf() does already.如果代码尝试在没有s*printf()的情况下执行此操作,则检查基于二进制的浮点数并转换为十进制以进行比较所涉及的数学将有效地重新执行sprintf()已经执行的操作。


Limitations:限制:

This answers is at best a start.这个答案充其量只是一个开始。 Consider foo(0.0, 0.0) and foo(DBL_TRUE_MIN, DBL_TRUE_MIN) here would return DBL_DECIMAL_DIG .考虑这里foo(0.0, 0.0)foo(DBL_TRUE_MIN, DBL_TRUE_MIN)将返回DBL_DECIMAL_DIG As DBL_TRUE_MIN is about 4.940656...e-324 yet as an exact decimal has about 751 significant digits, should 751 be returned?因为DBL_TRUE_MIN大约是 4.940656...e-324 而精确的小数大约有 751 位有效数字,应该返回 751 吗?

Research is needed also to consider edge cases .还需要研究以考虑边缘情况

See @Eric Postpischil good idea about first changing the rounding mode.请参阅@Eric Postpischil关于首先更改舍入模式的好主意。 IAC, using sprintf() is limited by a quality of implementation. IAC,使用sprintf()受实施质量的限制。


[Update] [更新]

If a C library implements FP perIEEE-754 , then to well handle many cases, a +3 to the precision is recommended.如果 C 库根据IEEE-754实现 FP,那么为了很好地处理许多情况,建议将精度提高到 +3。

char buf[N + 3 + 10];
// Consider changing round mode to "round towards 0.0.  See below notes.
snprintf(buf, sizeof buf,"%+.*e", DBL_DECIMAL_DIG + 3 - 1, value);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM