исключение с плавающей запятой в коде C

#c #int #bit #floating-point-exceptions

#c #int #бит #исключения с плавающей запятой

Вопрос:

 #include <stdio.h>
int test1(int x, int n){
    int times=31/n;
    return ((1-(1<<(n*times)))/(1-(1<<n)));
}
  

Я выполняю вычисление, где 1<=n<= 32

Это работает только тогда, когда 1 <= n<= 31, как я могу изменить его на n = 32? Когда я тестирую его случай n = 32 в xcode, он запускает отладчик и показывает поток 1 exc_arithmetic(code=exc_i386_div….
Заранее благодарю вас.

Комментарии:

1. В этом коде нет ничего , что можно было бы назвать «плавающей запятой» или «исключением»…

2. Как мы можем рассказать вам, как заставить его «работать», если вы не говорите нам, что он должен делать?

3. К чему должно привести целое 31/32 число?

4. @EugeneSh. В некоторых (вероятно, во многих) системах вы получите «исключение с плавающей запятой» при выполнении целочисленного деления на ноль. OP сообщает о том, что говорит ему его система, и, вероятно, будет делать это точно.

5. @Eugene Sh.: Не только деление на ноль, но и INT_MIN / -1 приводит к «исключению с плавающей запятой» в GCC.

Ответ №1:

Существует приличная вероятность того, что когда вы это сделаете 1 << 32 , оно будет обработано как 1 << 0 (и, поскольку вы вызываете неопределенное поведение, это нормально), и затем вы получите «исключение с плавающей запятой», потому что вы выполняете целое число «деление на ноль». В наши дни это наиболее распространенная причина исключения. Если бы вы выполняли арифметику с плавающей запятой, вы бы получили бесконечность, возвращаемую (молча) для деления на ноль.

Ответ №2:

Я только что узнал, как я могу это исправить. проблема 1<<32 в случае (которого я постараюсь избежать).

Я перешел 1 << n на (1 << (n-1) )*2 другой способ применения математики.

 return ((1-(1<<(n*times)))/(1- (1<<(n-1))*2  ));
  

Комментарии:

1. Если ваш int тип является 32-разрядным типом, вы по-прежнему вызываете неопределенное поведение. И если бы он был длиннее 32 бит, вы бы вообще не получили сообщение об ошибке. Можете ли вы объяснить, что должен оценивать ваш расчет?

2. @JonathanLeffler, то, что я делал, это ввод 32-разрядного int и числа n в качестве входных данных, а выходные данные должны быть заполнены повторяющимися n битами ввода. Например, если входные данные равны 1 и 2. (повторяющийся шаблон равен 01), на выходе должно быть 0x55555555. если входные данные равны 0x12345678, 32, на выходе будет просто 0x12345678. Я получаю результат, обнаружив, что могу вычислить сумму последовательных рядов. и тот, который я спрашиваю, является его частью.

Ответ №3:

Некоторые современные реализации для платформ с 2 дополнениями генерируют «исключение с плавающей запятой» в ответ на переполнение целочисленного деления, которое происходит в следующем коде

 int a = INT_MIN;
int b = -1;
int c = a / b;
  

даже думал, что там нет ничего «плавающего». GCC является одним из примеров такой платформы.

По-видимому, ваше выражение сталкивается с той же проблемой, что и практическое специфичное для платформы проявление неопределенного поведения, вызванного «перестановкой» целого числа.

PS Как отметил @Jonathan Leffler, целочисленное деление на ноль также генерирует «исключение с плавающей запятой» в GCC, что, вероятно, еще более вероятно в вашем случае.