5

如果实数可以用双精度表示,我如何编写返回 true 的 C++ 函数?

bool isRepresentable( const char* realNumber )
{
   bool answer = false;
   // what goes here?
   return answer;
}

简单测试:

assert( true==isRepresentable( "0.5" ) );
assert( false==isRepresentable( "0.1" ) );
4

6 回答 6

5

神圣的功课,蝙蝠侠!:)

有趣的是,您不能简单地执行 (atof|strtod|sscanf) -> sprintf 循环并检查是否恢复了原始字符串。例如,许多平台上的 sprintf 检测到“尽可能接近 0.1”双精度并将其打印为 0.1,即使 0.1 不能精确表示。

#include <stdio.h>

int main() {
    printf("%llx = %f\n",0.1,0.1);
}

打印:3fb999999999999a = 0.100000

在我的系统上。

真正的答案可能需要解析双精度以将其转换为精确的小数表示(0.1 = 1/10),然后确保 atof 转换乘以分母等于分子。

我认为。

于 2008-11-04T16:17:42.263 回答
5

将数字解析为 a + N / (10^k) 的形式,其中 a 和 N 是整数,k 是小数位数。

示例:12.0345 -> 12 + 345 / 10^4,a = 12,N = 345,k = 4

现在,10^k = (2 * 5) ^ k = 2^k * 5^k

当且仅当您去掉分母中的 5^k 项时,您才能将您的数字表示为精确的二进制分数。

结果将检查 (N mod 5^k) == 0

于 2008-11-04T18:18:53.157 回答
1

这是我的版本。sprintf 将 0.5 转换为 0.50000,最后的零必须被删除。

编辑:必须重写以正确处理以 0 结尾的不带小数点的数字(如 12300)。

bool isRepresentable( const char* realNumber )
{
   布尔答案=假;

   双 dVar = atof(realNumber);
   字符检查[20];
   sprintf(检查,“%f”,dVar);

   // 删除末尾的零 - TODO:仅当字符串中有小数点时才执行
   for (int i = strlen(check) - 1; i >= 0; i--) {
     if (check[i] != '0') 中断;
     检查[i] = 0;
   }

   答案 = (strcmp(realNumber, check) == 0);

   返回答案;
}
于 2008-11-04T16:11:32.273 回答
0

这应该可以解决问题:

bool isRepresentable(const char *realNumber)
{
    double value = strtod(realNumber, NULL);

    char test[20];
    sprintf(test, "%f", value);

    return strcmp(realNumber, test) == 0;
}

可能最好使用 sprintf 的“安全”版本来防止潜在的缓冲区溢出(在这种情况下甚至可能吗?)

于 2008-11-04T16:02:51.933 回答
0

我将字符串转换为其数字位表示(位数组或长整数),然后将字符串转换为双精度并查看它们是否匹配。

于 2008-11-04T16:03:32.103 回答
-2

将字符串转换为范围大于双精度的浮点数。将其转换为双倍,看看它们是否匹配。

于 2008-11-04T16:01:48.270 回答