【发布时间】:2010-05-12 16:58:47
【问题描述】:
在 Redis (http://code.google.com/p/redis) 中有与元素相关的分数,以便对这些元素进行排序。这个分数是双倍的,即使许多用户实际上是按整数排序(例如 unix 时间)。
保存数据库后,我们需要写入这个双倍好的磁盘。这是目前使用的:
snprintf((char*)buf+1,sizeof(buf)-1,"%.17g",val);
另外检查无穷大和非数字条件,以便在最终的数据库文件中也表示这一点。
不幸的是,将 double 转换为字符串表示非常慢。虽然我们在 Redis 中有一个函数,可以以更快的方式将整数转换为字符串表示形式。所以我的想法是检查是否可以将双精度转换为整数而不会丢失数据,然后使用该函数将整数转换为字符串,如果这是真的。
为了提供良好的加速,整数“等价”的测试当然必须很快。所以我使用了一个可能是未定义行为的技巧,但在实践中效果很好。类似的东西:
double x = ... some value ...
if (x == (double)((long long)x))
use_the_fast_integer_function((long long)x);
else
use_the_slow_snprintf(x);
在我的推理中,上面的双重转换将双精度转换为长整数,然后再转换回整数。如果范围合适,并且没有小数部分,则该数字将在转换后继续存在,并且与初始数字完全相同。
因为我想确保这不会破坏某些系统中的东西,所以我在 freenode 上加入了#c,我受到了很多侮辱;)所以我现在在这里尝试。
是否有一种标准方法可以在不超出 ANSI C 的情况下完成我想做的事情?否则,上面的代码是否应该在当前 Redis 目标的所有 Posix 系统中工作?也就是说,现在运行 Linux / Mac OS X / *BSD / Solaris 的拱门?
为了使代码更清晰,我可以添加的是在尝试强制转换之前明确检查双精度的范围。
感谢您的帮助。
【问题讨论】:
-
讨厌侮辱,伙计。我不知道答案,但我希望你能找到答案。
-
如果有帮助,stackoverflow.com/questions/638376/… 是在 C# 中检查这一点的一种方式。我还没有找到 C 版本。
-
或者我可以使用 modff() 检查小数部分是否为零?然后检查整数部分的范围是否在long long的范围内,如果是则强制转换。
-
如果您只担心将它们存储为稍后检索的文本并实现了快速整数转换,那么您还应该能够实现快速浮点作为“基数到指数”转换只比转换 2 个整数稍微复杂一点。
标签: c casting integer double printf