Разница в C ++ верна после переполнения - PullRequest
1 голос
/ 08 ноября 2011

Мне просто интересно, останутся ли различия правильными из-за переполнения.Например, я пытаюсь использовать таймер высокого разрешения Windows с QueryPerformanceFrequency (& local).

Начальное значение этого счетчика не определено.Однако интересным моментом является только отличие от отправной точки.Итак, в начале вы записываете значение, а затем всегда смотрите на разницу.Теперь, если я могу гарантировать, что разница не будет больше, чем LARGE_INTEGER, достаточно ли этого?

Скажем, например, у одного есть 4 бита.Это позволяет 1 ... 15.Если счетчик теперь начинается с 14 и останавливается на 2, а я делаю 2 - 14, я должен получить 4, не так ли?Поэтому мне не нужно беспокоиться о переполнении, если разница меньше?

Спасибо

Ответы [ 4 ]

3 голосов
/ 08 ноября 2011

Поскольку вы используете структуру, специфичную для Windows, ваша проблема проще, так как она должна работать только на машинах, которые поддерживают Windows. Windows требует арифметики с двойным дополнением, а арифметика с двойным дополнением ведет себя при переполнении ожидаемым образом (переполнения вычисляются в моде 2 ^ n).

1 голос
/ 08 ноября 2011

Я не собираюсь отвечать на общий вопрос, а скорее на конкретный: вам нужно беспокоиться о переполнениях из QueryPerformanceCounter?

Если у вас есть счетчик производительности, который увеличивается с частотой 4 ГГц, 63-разрядное целое число со знаком для преобразования в отрицательное число займет 73 года. Не нужно беспокоиться о переполнении.

0 голосов
/ 08 ноября 2011

Используя дополнение 2 (способ представления целых чисел в компьютерах), вы можете добавлять или вычитать несколько чисел - и результат будет правильным , если он соответствует количеству выделенных бит .Временные результаты не обязательно должны соответствовать выделенному количеству битов.

Так что да, если вы используете целое число из N битов, вы получите правильный результат, если разница меньше 2 ^ N.

0 голосов
/ 08 ноября 2011

По крайней мере, на моем компьютере определение LARGE_INTEGER:

typedef union _LARGE_INTEGER {
     struct {
         DWORD LowPart;
         LONG HighPart;
     };
     LONGLONG QuadPart; 
 } LARGE_INTEGER;

Сложная часть - все они подписаны.Так что, если у вас есть четыре бита, диапазон (-8,7).Затем, если вы начнете с 6 и остановитесь на 0, вы получите разницу -6.

Однако, если вы приведете LONGLONG к unsigned long long (либо до, либо после вычитания, либо в порядке), то вы получите правильный ответ.Преобразование -6 в unsigned long long дает 10, правильную разницу.

...