pow

andr2510
Offline
Зарегистрирован: 12.03.2018

Добрый день.

Обзавелся я Arduino nano 328.

Вроде как все элементарно. Нужно мне цифру 2 возвести в степень и получить массив чисел int  в котороых только один бит равен 1.

Грешным делом подумал, что сделаю так:

for(int i=0;i<8;i++)
  newint=pow(2,i);

В итоге я почему то получаю последовтаельносьт 1,2,3....

А если напишу pow(2,2) то получу 4.

Вопрос. Что не так? Почему, если я в цикле гоняю, то 2 в степени i равному 2 я получаю 3? Я всю голову сломал. В итоге я вручную забил массив {1,2,4,8,16....} но, блин, это не выход.

Вопрос пошел, на самом деле, с того, что я хотел мигать светодиодами подключенными к 595 и последовательно в loop хотел просто писать 1, потом, 2, потом 4 итд. Тем самым мигая ими последовательно. Но увидел полную туфту. Я час проверял схему. Но выяснилось, что проблема в математике причем там, где я вообще не ожидал "камней". Потом я подумал, что глобальная переменная int i которая в loop каждый раз увеличивается, может быть, как то преобразуется. Но нет. В цикле pow так же возвращает туфту.

sadman41
Offline
Зарегистрирован: 19.10.2016

Не вижу оператора вывода переменной newint...

kalapanga
Offline
Зарегистрирован: 23.10.2016

При присвоении double к int потерялось, не иначе. Надо самому округлять желаемым способом. (сейчас происходит просто отсечение)

andr2510
Offline
Зарегистрирован: 12.03.2018

Не вижу оператора вывода переменной newint...

Я его сюда не писал, а зачем?

sadman41
Offline
Зарегистрирован: 19.10.2016

andr2510 пишет:

Не вижу оператора вывода переменной newint...

Я его сюда не писал, а зачем?

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

andr2510
Offline
Зарегистрирован: 12.03.2018

kalapanga пишет:

При присвоении double к int потерялось, не иначе. Надо самому округлять желаемым способом. (сейчас происходит просто отсечение)

Я конечно попробую.... но объясните мне, какой оперцией "отсечения" происходит преобразование числа 0000 0100 в 0000 0011? Я не понимаю логику поведения тогда

andr2510
Offline
Зарегистрирован: 12.03.2018

sadman41 пишет:

andr2510 пишет:

Не вижу оператора вывода переменной newint...

Я его сюда не писал, а зачем?

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

Согласен. 

Сначала я писал с помощью "shiftOut"

Потом делал serial.out(String(newInt)); Сама переменная типа int.

Вот может быть реально преобразование идет как написал другой автор. Но пока не понимаю, как? А если сейчас попробую и увижу, что действииельно в этом дело, то буду в шоке и уйду в монастырь. Ибо double в int может перейти с отсечением, но отсекутся лишние 8 бит и 100 в 011 никак не пойму, как могут преобразоваться.

b707
Offline
Зарегистрирован: 26.05.2017

andr2510 пишет:

объясните мне, какой оперцией "отсечения" происходит преобразование числа 0000 0100 в 0000 0011? Я не понимаю логику поведения тогда

"Элементарно, Ватсон"

Число b0000 0100 в формате double вполне может записываться как 3.99999999

Дальше продолжать?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

просто запомни на будущее, что pow(2,n) тождественно 1<<n;

Olej
Olej аватар
Offline
Зарегистрирован: 05.03.2018

DetSimen пишет:

просто запомни на будущее, что pow(2,n) тождественно 1<<n;

Лучший совет на сегодня.

 

sadman41
Offline
Зарегистрирован: 19.10.2016

b707 пишет:

Число b0000 0100 в формате double вполне может записываться как 3.99999999

Дальше продолжать?

Проиллюстрирую:

void setup() {
  Serial.begin(9600);
  int newint;
  float pownum;
  for (int i = 0; i < 8; i++) {
    pownum = pow(2, i);
    Serial.println(pownum, 8);
    newint = int(pownum+0.5);
    Serial.println(newint);
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

 

b707
Offline
Зарегистрирован: 26.05.2017

Степени двойки вообще проще всего формировать битовым сдвигом влево.

byte x =1;
byte newint;
for(int i=0;i<8;i++)
  newint= x << i;

 

 

апаздал...

andr2510
Offline
Зарегистрирован: 12.03.2018

b707 пишет:

Степени двойки вообще проще всего формировать битовым сдвигом влево.

byte x =1;
byte newint;
for(int i=0;i<8;i++)
  newint= x << i;

 

Да, есть 100500 способов решения. Но мне нужно было понять, что не так с pow.

Olej
Olej аватар
Offline
Зарегистрирован: 05.03.2018

andr2510 пишет:
Но мне нужно было понять, что не так с pow.

Вещественная арифметика:

double pow (double __x, double __y)

(это прототип из библиотеки).

 

ven-til
Offline
Зарегистрирован: 13.02.2018

andr2510 пишет:
что не так с pow.

С ним все хорошо, а если не нравится как работает, то можно написать свой pow чисто для int

andr2510
Offline
Зарегистрирован: 12.03.2018

ven-til пишет:

andr2510 пишет:
что не так с pow.

С ним все хорошо, а если не нравится как работает, то можно написать свой pow чисто для int

 

Это понятно, что я вряд ли нашел мегабаг))

Я не округляю. Не учел, что точность может "хромать".

Забавно что код:

int i = 2;
myint = pow(2, i);

вернет 4, а вот, если i  будет в цикле, то резульатат будет 3.

Olej
Olej аватар
Offline
Зарегистрирован: 05.03.2018

andr2510 пишет:

Забавно что код:

int i = 2;
myint = pow(2, i);

вернет 4, а вот, если i  будет в цикле, то резульатат будет 3.

О! Да ты шама-а-а-а-а-ан ! ;-)