如果实数可以用双精度表示,我如何编写返回 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" ) );
如果实数可以用双精度表示,我如何编写返回 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" ) );
神圣的功课,蝙蝠侠!:)
有趣的是,您不能简单地执行 (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 转换乘以分母等于分子。
我认为。
将数字解析为 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
这是我的版本。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); 返回答案; }
这应该可以解决问题:
bool isRepresentable(const char *realNumber)
{
double value = strtod(realNumber, NULL);
char test[20];
sprintf(test, "%f", value);
return strcmp(realNumber, test) == 0;
}
可能最好使用 sprintf 的“安全”版本来防止潜在的缓冲区溢出(在这种情况下甚至可能吗?)
我将字符串转换为其数字位表示(位数组或长整数),然后将字符串转换为双精度并查看它们是否匹配。
将字符串转换为范围大于双精度的浮点数。将其转换为双倍,看看它们是否匹配。