C++ 警告:转换为';双倍';从';长整型';可能会改变它的价值
我的代码如下:C++ 警告:转换为';双倍';从';长整型';可能会改变它的价值,c++,linux,g++,compiler-warnings,C++,Linux,G++,Compiler Warnings,我的代码如下: #include <iostream> #include <sys/time.h> using namespace std; int main(int argc, char** argv) { if(argv[0]) argc++; struct timeval m_timeEnd, m_timeCreate, m_timeStart;
#include <iostream>
#include <sys/time.h>
using namespace std;
int main(int argc, char** argv) {
if(argv[0])
argc++;
struct timeval m_timeEnd, m_timeCreate, m_timeStart;
long mtime, alltime, seconds, useconds;
gettimeofday(&m_timeStart,NULL);
sleep(3);
gettimeofday(&m_timeCreate,NULL);
sleep(1);
gettimeofday(&m_timeEnd, NULL);
seconds = m_timeEnd.tv_sec - m_timeStart.tv_sec;
useconds = m_timeEnd.tv_usec - m_timeStart.tv_usec;
mtime = (long) (((seconds) * 1000 + useconds/1000.0) + 0.5);
seconds = useconds = 0;
seconds = m_timeEnd.tv_sec - m_timeCreate.tv_sec;
useconds = m_timeEnd.tv_usec - m_timeCreate.tv_usec;
alltime = (long) (((seconds) * 1000 + useconds/1000.0) + 0.5);
printf("IN=%ld ALL=%ld milsec.\n", mtime, alltime);
}
这应该起作用:
mtime = (long)(((long long)seconds*1000000 + useconds + 500)/1000);
以相同的方式转换所有时间的表达式
看到这些警告的原因是,表达式从long转换为double,然后再转换回double进行计算。您可以通过将表达式重新洗牌一点以完全保留在整数类型中来避免它。注意转换为long
以避免溢出(谢谢,尼克)
编辑您可以进一步简化此操作并消除转换:
mtime = seconds*1000 + (useconds + 500)/1000;
最令人讨厌的方式是
mtime = (long) (((double)seconds * 1000.0 + (double)useconds/1000.0) + 0.5);
这将删除任何警告…如果您真的不需要舍入到最接近的毫秒的值-也就是说,如果您可以承受高达1毫秒而不是1/2毫秒的不准确度-您可以简单地写入
mtime = seconds * 1000 + useconds / 1000;
否则,它将不得不
mtime = seconds * 1000 + (useconds / 500 + 1) / 2;
编辑:或不编辑。请参阅注释。也将其更改为:
mtime = seconds * 1000 + useconds/1000;
不同之处在于它没有四舍五入到最接近的微秒(它向下四舍五入)
无论如何,没有那么精确的计时器
如果你真的必须有额外的准确性(四舍五入到最近的,而不是四舍五入到地板)
这不是有溢出的危险吗?@Nick你是对的,我添加了一个到long
的转换,然后返回到long
来解决这个问题。谢谢在sizeof(long)=sizeof(long-long)的系统上发生的情况。在一般情况下,这并不能保护您不受溢出。因为它是C++,所以不应该使用C样式的转换。我指的是在代码中搜索搜索的部分。无论如何,我最近读到了一个更具说服力的解释:基于此,我发现你上面的评论相当可疑。它以“我知道我在做什么,停止警告我”的方式删除了警告;不是以“我解决了问题”的方式。@LokiAstari-我确实以“hacky way”的方式获得了资格…)+1:我花了一段时间才弄明白你在用第二个表达式做什么。你可能想解释一下它是如何工作的。@LokiAstari我的公式和你的完全一样,只是你的更简单。然而,我们两人都完全忽视了这样的事实,即这样的舍入对负数不起作用,useconds可以是负数!因此,公式实际上应该是mtime=seconds*1000+((usec+)(usecAre)你确定。如果微秒为负数,许多与timeval相关的宏都将中断。此外,它还被定义为从历元开始的秒和微秒。如果在usec中允许负数,秒部分也将为负数(因为你会在负方向上从历元开始计数(我想,但我怀疑任何一种方法是否有效(或者我不相信它会起作用))。同样,四舍五入到最接近的微秒是愚蠢的。只需截断值(四舍五入到零)与第一个示例一样,所有操作都将按照用户的预期进行。@LokiAstari是的,尽管timeval结构中的值不会为负值,但此useconds
是两个长的减法结果(请参见原始问题).关于精度,你当然是对的,但问题是如何消除警告,而不是如何重写计算使其更简单。
mtime = seconds * 1000 + useconds/1000;
// Add 500 to useconds so that when we divide by 1000 we effectively
// round to nearest rather than truncate thus rounding to floor
mtime = seconds * 1000 + (useconds + 500) / 1000;