#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, что, вероятно, еще более вероятно в вашем случае.