Переполнение Вопросы о числах и числах с плавающей точкой × целые числа - PullRequest
1 голос
/ 09 августа 2010

1) Это не переполняется?

long long v1, v2, result;
[..]
result = ((long double) v1 / v2) * 1000000LL;

1.a) Могу ли я опустить LL на константу? И почему.

2) Альтернативно, этот вариант без поплавка в порядке?

long long l1, l2, result;
[..]
result = (1000000 * (v1 / v2) + v1 % v2);

2.a) У кого больше накладных расходов? 1-й или этот пример?

3) Может ли плавающее число когда-либо переполняться или просто переноситься на «нормальные» значения?

Ответы [ 2 ]

2 голосов
/ 09 августа 2010

Да, результат в примере (1) может легко переполниться, если, скажем, v1 = 1000000000000000 и v2 = 1. Вам не нужен LL для этой константы, потому что он достаточно мал, чтобы поместиться в int ( в большинстве случаев, в любом случае).

(2) Это может переполниться так же, как в примере 1, если v1 и v2 такие, как я их дал.

Первый пример более дорогой, так как арифметика с плавающей запятой дороже, чем целочисленная арифметика.

(3) Число с плавающей точкой, безусловно, может быть переполнено, и последствия зависят от реализации.

Как указал Арджит, вы можете предотвратить переполнение, проверив значение v1 перед выполнением расчета. Если v1 может быть отрицательным, вам также необходимо проверить отрицательную версию, и, возможно, следующее может быть лучше ...

if ((LONG_LONG_MAX / 1000000) > V1)
{
...
}

Если вы действительно не вписываетесь в лимит, вы можете увеличить свой запас, объявив переменные unsigned.

Позже - отредактируйте, чтобы исправить ошибку, указанную Арджитом.

1 голос
/ 09 августа 2010

Во-первых

  1. , если при выполнении вычисления INT или Long не использовать float.Потому что ваш результат в первой части будет иметь много разных значений, которые почти равны.

Потому что (float) v1 / v2 = ab.cdef.// где cdef может варьироваться.

Ваша вторая реализация также может вызвать переполнение, если v1 = 2 ^ 15 и v2 = 1

, поэтому, если вы ищете переполнение и безопасность, вы всегда должны проверять

как 2 ^ 18 / Константа, которая в данном случае равна 1000000

, поэтому

if(2^18/Constant > v1)

    result = (1000000 * (v1 / v2) + v1 % v2);

Это может быть любым доказательством взлома.

Надеюсь, это поможет

...