2016-09-22 7 views
2

Используя pow() из библиотеки <cmath>, я получаю отрицательное число для некоторых чисел.Почему pow() в C++ возвращает отрицательный номер

2601*((int)pow(10.0,3*2)) = -1693967296 

Почему это так? Это связано с тем, что int имеет диапазон от -32767 до 32767? Или это из-за кастинга?

+1

Int32 обертывает –

+0

целочисленное переполнение .. цифры намного больше и округляются до большого отрицательного числа при переполнении, если int подписан. –

+0

Если вам нужно выполнить этот вид вычислений без переполнения, вам понадобится Арифметика больших чисел: http://www.cs.utexas.edu/users/djimenez/utsa/cs3343/lecture20.html – user2346536

ответ

5

Поведение вашей программы undefined, поскольку вы переполняете подписанный интегральный тип.

pow(10.0, 3 * 2) is не возвращение отрицательного номера. Эта конкретная перегрузка вернет double. Вы бросаете это на int, а затем умножаете его на константу. Это слишком велико, чтобы вписаться в int. Вы проверили INT_MAX (или эквивалент std::numeric_limits<int>::max()) на своей платформе?

+1

Мне кажется, что возвращение из pow действительно вписывается в int, и это умножение, которое переполняется. – plugwash

+0

Вы правы. Спасибо, что указали это. Я исправил ответ. – Bathsheba

2

Это не pow(), но вы превзошли ответ.

10 к 6-му власти миллион, и в миллион раз 2,601 является

2,601,000,000 

Для целых чисел на вашей платформе, диапазон, вероятно,

–2,147,483,648 to 2,147,483,647 

Таким образом, вы видите, вы» ve превысили этот диапазон. Фактическая разница переполнения может показаться непоследовательной, но из-за формы дополнения двух.

+1

Ваш диапазон true для 2-го дополнения 32-битная подпись 'int'. – Bathsheba

+0

Да, это правда. Я делаю (возможно, неверное) предположение о платформе. Но это самый распространенный, по моему опыту. –

+0

Я знаю, что вы на самом деле имеете в виду, но если бы вы сказали, что на теге C у вас будут встроенные ребята после вас. Но серьезно, ваше утверждение диапазона разрушает этот ответ. – Bathsheba

2

Это из-за переполнения целого числа.

2601*1000000 > INT_MAX. 

Следовательно, переполнение.

+1

Picky Я знаю, но INT_MAX не находится в 'std' – Bathsheba

+0

@Bathsheba thanks – v78

0

Да, это из-за int данные типа. INT диапазон составляет от -2147483648 до 2147483647, так как SizeOf (INT) составляет 4 байта.

Чтобы преодолеть это, вы можете использовать неподписанных INT или долго ИНТ

+0

« int range от -2,147,483,648 до 2,147,483,647, потому что sizeof (int) составляет 4 байта ». Действительно, иногда это правильно. Но стандарт C++ не настаивает на этом. Хуже того, 'unsigned' может быть от 0 до 65535, поэтому в этом случае не поможет. – Bathsheba

+0

да. Unsigned может быть от 0 до 65535 в случае 16-разрядных систем компилятора. Но, сужая вышеупомянутую проблему, вопросник использует 32-битную систему компилятора. Если вы свободны, посмотрите на это https://ideone.com/KZagQB: P – Kumar

+0

«long int» на многих системах не больше, чем int. «long long int», с другой стороны, гарантируется как минимум 64 бита (и практически ровно 64 бит). – plugwash

0

Ваша платформа, как представляется, имеют 32-битный Int. Это поддерживает диапазон от -2147483648 до 2147483647

pow() возвращает положительное число в число с плавающей запятой двойной точности. Этот бит работает отлично.

Ваш персонаж преобразует это в int, снова это прекрасно.

Если все пошло не так, это умножение. Переполнение переполнения, подписанное переполнение - неопределенное поведение.

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

Смежные вопросы