Проблема переполнения целочисленного значения в C ++ при преобразовании типа double в unsigned int - PullRequest
0 голосов
/ 25 июня 2010

Мне нужно преобразовать время из одного формата в другой в C ++, и оно должно быть кросс-платформенным.Я создал структуру как мой контейнер времени.Поля структуры также должны быть unsigned int, как указано в устаревшем коде.

struct time{   
unsigned int timeInteger;   
unsigned int timeFraction;
} time1, time2;

Математически преобразование выглядит следующим образом:

time2.timeInteger = time1.timeInteger + 2208988800

time2.timeFraction = (time1.timeFraction * 20e-6)* 2e32

Вот мой оригинальный код на C ++, однако, когда я пытаюсь записать в двоичный файл, преобразованное время не совпадает с данными истинности.Я думаю, что эта проблема из-за ошибки приведения типа?Этот код скомпилируется в VS2008 и выполнится.

void convertTime(){
   time2.timeInteger  = unsigned int(time1.timeInteger + 2209032000);
   time2.timeFraction = unsigned int(double(time1.timeFraction) * double(20e-6)*double(pow(double(2),32)));
}

Ответы [ 3 ]

2 голосов
/ 25 июня 2010

Просто предположение, но вы предполагаете, что 2e32 == 2^32?Это предположение имело бы смысл, если вы пытаетесь масштабировать результат в 32-битное целое число.На самом деле 2e32 == 2 * 10^32

1 голос
/ 25 июня 2010

Немного не связано, я думаю, вы должны переосмыслить ваш тип дизайна. Вы в основном говорите о двух разных типах здесь. Они хранят одни и те же данные, хотя и с разными результатами.

Чтобы свести к минимуму ошибки при их использовании, вы должны определить их как два совершенно разных типа, которые имеют четко определенное преобразование между ними.

Рассмотрим для примера:

struct old_time {
    unsigned int timeInteger;   
    unsigned int timeFraction;
};

struct new_time {
public:
    new_time(unsigned int ti, unsigned int tf) :
        timeInteger(ti), timeFraction(tf) { }

    new_time(new_time const& other) :
        timeInteger(other.timeInteger),
        timeFraction(other.timeFraction) { }

    new_time(old_time const& other) : 
        timeInteger(other.timeInteger + 2209032000U),
        timeFraction(other.timeFraction * conversion_factor) { }

    operator old_time() const {
        old_time other;
        other.timeInteger = timeInteger - 2209032000U;
        other.timeFraction = timeFraction / conversion_factor;
        return other;
    }

private:
    unsigned int timeInteger;   
    unsigned int timeFraction;
};

(РЕДАКТИРОВАТЬ: конечно, этот код не работает по причинам, указанным ниже.

Теперь этот код можно безопасно использовать без трения:

time_old told; /* initialize … */

time_new tnew = told; // converts old to new format
time_old back = tnew; // … and back.
0 голосов
/ 25 июня 2010

Проблема в том, что (20 ^ -6) * (2 e32) намного больше, чем UINT_MAX. Возможно, вы имели в виду 2 для степени 32 или UINT_MAX, а не 2e32.

Кроме того, ваша первая строка с целым числом, начальное значение должно быть меньше (2 ^ 32 - 2209032000), и в зависимости от того, в чем это измеряется, оно может также округляться По моему мнению, установите первое значение как long long (обычно 64 бита) и измените 2e32.

Если вы не можете изменить тип, тогда может возникнуть необходимость сохранить поле, например, в результате двойного результата, а затем привести к типу unsigned int перед использованием.

...