предупреждение: преобразование в 'double' из 'long int' может изменить его значение - PullRequest
4 голосов
/ 10 февраля 2012

Мой код следующий:

#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);

}

Я компилирую с

g ++ -W -Wall -Wno-unknown-pragmas -Wpointer-arith -Wcast-align -Wcast-qual -Wsign-сравнить -Wconversion -O -fno-строгого псевдонима

и у меня есть несколько предупреждений, которые мне нужно устранить. Как?

a1.cpp:21: warning: conversion to 'double' from 'long int' may alter its value
a1.cpp:21: warning: conversion to 'double' from 'long int' may alter its value
a1.cpp:25: warning: conversion to 'double' from 'long int' may alter its value
a1.cpp:25: warning: conversion to 'double' from 'long int' may alter its value

Ответы [ 4 ]

3 голосов
/ 10 февраля 2012

Если вы не действительно нуждаетесь в значении, округленном до ближайшей миллисекунды - то есть, если вы можете жить с погрешностью до 1 миллисекунды вместо 1/2 миллисекунды - вы можете просто написать

mtime = seconds * 1000 + useconds / 1000;

В противном случае это должно быть

mtime = seconds * 1000 + (useconds / 500 + 1) / 2;

Редактировать : или нет. Смотрите комментарий.

1 голос
/ 10 февраля 2012

Измените это тоже:

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;
0 голосов
/ 10 февраля 2012

Хакерский способ - читать ...

mtime = (long) (((double)seconds * 1000.0 + (double)useconds/1000.0) + 0.5);

Это удаляет все предупреждения ...

0 голосов
/ 10 февраля 2012

Это должно работать:

mtime = (long)(((long long)seconds*1000000 + useconds + 500)/1000);

Преобразуйте выражение для alltime таким же образом.

Причина, по которой вы видите предупреждения, состоит в том, что ваше выражение преобразуется из длинного в двойное иназад, чтобы сделать математику.Вы можете избежать этого, немного перетасовывая выражения, чтобы полностью оставаться внутри целочисленных типов.Обратите внимание на преобразование в long long, чтобы избежать переполнения (спасибо, Ник).

РЕДАКТИРОВАТЬ Вы можете еще больше упростить это и исключить преобразование:

mtime = seconds*1000 + (useconds + 500)/1000;
...