如果实数可以用double精确表示,我怎么能写一个C ++函数返回true?

时间:2008-11-04 15:50:48

标签: c++ floating-point

如果真实数字可以用双精确表示,我怎么能写一个C ++函数返回true?

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

简单测试:

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

6 个答案:

答案 0 :(得分: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

在我的系统上。

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

我想。

答案 1 :(得分:5)

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

示例:12.0345 - &gt; 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

答案 2 :(得分:1)

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

编辑:必须重写以处理没有小数点且正确结束的数字(如12300)。

bool isRepresentable( const char* realNumber )
{
   bool answer = false;

   double dVar = atof(realNumber);
   char check[20];
   sprintf(check, "%f", dVar);

   // Remove zeros at end - TODO: Only do if decimal point in string
   for (int i = strlen(check) - 1; i >= 0; i--) {
     if (check[i] != '0') break;
     check[i] = 0;
   }

   answer =  (strcmp(realNumber, check) == 0);

   return answer;
}

答案 3 :(得分:0)

这应该可以解决问题:

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

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

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

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

答案 4 :(得分:0)

我将字符串转换为数字位表示(位数组或长数字),然后将字符串转换为double,看看它们是否匹配。

答案 5 :(得分:-2)

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