Чи існує неплаваюча альтернатива pow ()?


9

Я переглянув МОВЛЕННУ ПОСИЛАННЯ на веб-сайті Arduino , і я не можу знайти еквівалент неплавкого, що pow() мені не вистачає чогось великого, але на все життя я наткнувся! Я знайшов pow()у колонці FUNCTIONS під заголовком Math (як я б очікував), але в ньому написано, що обидва параметри, [base] і [exponent], обидва (float). І під заголовком Математика є лише шість інших записів; жоден з них не здається цілою версією. Все, що я хочу зробити, це генерувати сили 2, використовуючи експоненти від 0 до 10. Як і 2 ^ 0 = 1, тоді 2 ^ 1 = 2, то 2 ^ 2 = 4, то 2 ^ 3 = 8, то 2 ^ 4 = 16, то 2 ^ 5 = 32, то 2 ^ 6 = 64, то 2 ^ 7 = 128, то 2 ^ 8 = 256, то 2 ^ 9 = 512, то 2 ^ 10 - 1024

Чи використання плавців є єдиним способом це зробити? Я починаю відчувати, що мені суперечать реальність, і насправді порахував ліки, але я прямо там, де маю бути. Дозвольте мені заздалегідь вибачитися за цей жахливий нагляд, який я витрачав ваш час, але я пройшов усі 9 сторінок тегів і здійснив будь-який пошук, про який я міг придумати. Я визнаю, що я не витратив стільки часу, але я був впевнений, що це буде лише п’ять хвилин!


2
У загальному випадку цілого потужна (), см stackoverflow.com/questions/101439 / ... . Для потужностей 2 використовуйте лише зміни.
Пітер Кордес

Відповіді:


8

У загальному випадку відповідь @dat_ha правильна, але варто зазначити, що ви хочете дуже особливий випадок ... повноваження двох. Оскільки комп'ютери використовують двійкову арифметику, для операцій із двома силами часто доступні деякі ярлики.

Помноження числа на потужність двох може бути здійснено операцією зсуву ліворуч ( <<), яка буквально зміщує цифри двійкового зображення числа (тобто біт) наліво. У другій базі зміщення бітів на одне місце ліворуч - це те саме, що множення на 2, так само, як у базі 10 зміщення цифр, одне місце вліво - це те саме, що множення на 10. Для повного пояснення оператора лівої зміни в C ++ , див. цю відповідь на переповнення стека .

Важливо зазначити, що зміщення ліворуч може втратити інформацію; біти, зміщені від кінця, втрачаються. Оскільки вам потрібні потужності від 2 до 10, ви безпечні при роботі з підписаними цілими числами, які мають максимальне значення 2^15-1на Arduino Uno .

Враховуючи ці застереження, ось функція обчислювати сили двох у межах цих обмежень. Це дуже швидкий код, оскільки операція зсуву ліворуч - це операція дуже низького рівня, і множення насправді не виконується.

int pow2(int p){
    return 1 << p;
}

Помилка: якщо ви користуєтесь an, вона може перевищувати 2 ^ 32 - 1 unsigned long.
Дат Ха

@DatHa дякую, я, здавалося, втратив слово "підписаний" під час редагування. Виправлено.
Джейсон Кларк

1
Це може пройти повз 2 ^ 32 - 1, якщо ви використовуєте реалізацію довільної арифметики точності з цілою цілістю
Dat Han Bag

Мені хотілося б спеціально знати, чому результати цілочислового перетворення на результати pow () НЕ працюють для потужностей 2. Для мене pow (2,3) повертає 8.00, але в той час, як int (8.00) повертає 8 , int (pow (2,3)) повертає 7!
KDM

1

Він працює з int, double, longі float. unsigned longі unsigned intтакож має працювати. Вам не потрібно використовувати ТОЛЬКО плавці.

Сподіваюся, це допомогло!


Причина, з якою працює відповідь вище, полягає в тому, що множина дійсних чисел (які містять поплавці) містить безліч цілих чисел
Dat Han Bag

@DatHanBag: І що ще важливіше, кожне 32-бітове ціле число точно представлене a double. Насправді, оскільки плаваюча точка IEEE заснована на бінарному представленні мантіси / експонента, кожна потужність 2 повинна бути точно представлена ​​навіть поза 2 ^ 53 (точка, де doubleне можна представляти кожне довільне ціле число, 1 одиниця в останньому місці мантіса більша за 1,0).
Пітер Кордес

@PeterCordes Так, я це знав. Можливо, я мав би сказати "обмежені множини", коли згадував про float та integer множини для arduino в своєму коментарі про відповідь
Dat Han Bag

4
Це дещо pow()вагома відповідь на загальне питання використання для цілих чисел, але AFAICT arduino навіть не має апаратної плаваючої точки, тому це страшна відповідь. Ціла pow()реалізація на кшталт цієї, яка працює в log2 (n) множення часу та додавання для накопичення результату, майже напевно, ймовірно, буде краще, а якщо не згадати, що зміна бітів працює для повноважень 2, просто робить це страшною відповіддю на це питання.
Пітер Кордес

1
@PeterCordes "так це страшна відповідь". -погодився, що це якась спрощена відповідь низької якості. pow (), безумовно, можна обчислити в log2 (n) - простий метод, засвоєний у школі (множення числа на себе на потужність не настільки ефективний). Можна зробити це краще за допомогою перетворення Фур'є для дійсно великих цілих чисел - наприклад. Але, можливо, ОП прийме і сподобається.
Дат Хан Сумка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.