Прошу помочь разобраться - кто хуже в школе учился я или МК?
Столкнулся с интересным феноменом, ковыряя ардуину со сдвиговым регистром 74HC595: встроенная в среду функция возведения в степень (pow()) работает на мой взгляд некорректно. Потребовалось мне двоечку в степень n возводить, а само число в виде переменной оформлено, которой разные целые значения присваиваются. Но прикол в том, что если например 2^0 или 2^1 считаются правильно, то все остальное на 1 меньше ожидаемого результата, то есть 2^2=3, 2^3=7, 2^4=15 и т.д. Помучался я с этим немного, плюнул, сделал все через битовый сдвиг, но осадочек остался. Может кто сталкивался с подобным поведением?
Не важно чем все начнется. Важно чем кончится!
- Реклама
- Сообщения: 12867
- Зарегистрирован: Сб дек 18, 2021 19:25:32
тип аргументов pow() - с плавающей запятой. результат тоже .Приведение к целому вполне может сделать на 1 меньше.
[uquote="Martian",url="/forum/viewtopic.php?p=4379112#p4379112"]тип аргументов pow() - с плавающей запятой. результат тоже .Приведение к целому вполне может сделать на 1 меньше.[/uquote]
Ну я так и понял - функция весьма кривая - как и все ардуиновское. Недавно хотел по быстрому с TM1628 разобраться используя библиотеки - исплевался от злости, а решения так и не нашел. Плюнул и внял способу RTFM - только после этого все получилось в лучшем виде. MAX5400 так же осваивал - под него вообще библиотек нет. Библиотеки это зло...
Ну я так и понял - функция весьма кривая - как и все ардуиновское. Недавно хотел по быстрому с TM1628 разобраться используя библиотеки - исплевался от злости, а решения так и не нашел. Плюнул и внял способу RTFM - только после этого все получилось в лучшем виде. MAX5400 так же осваивал - под него вообще библиотек нет. Библиотеки это зло...
Не важно чем все начнется. Важно чем кончится!
- Сообщения: 12867
- Зарегистрирован: Сб дек 18, 2021 19:25:32
Функция не кривая. У Вас неверное представление о машинных арифметических действиях с разными типами данных. Думаете, в других мк/языках/средах нет подобных нюансов? Ещё как есть.
И библиотеки не зло.
И библиотеки не зло.
Еще как ! Иногда тратится очень много времени на поиски таких "чудес"Martian писал(а):Думаете, в других мк/языках/средах нет подобных нюансов? Ещё как есть.
Исходно, процессор кроме как складывать, вообще ничего не умеет
- Реклама
[uquote="Alexey1969",url="/forum/viewtopic.php?p=4379165#p4379165"]Исходно, процессор кроме как складывать, вообще ничего не умеет
[/uquote]Не только процессор! Топикстартер тоже. Он, похоже, не знает, что возведение в (любую) степень делается через логарифм и экспоненту, а ожидает от МК лишь целочисленных умножений, суть многократных сложений. Плохо, видать, в школе учился...
Всего доброго.
Евгений.
Евгений.
Не знание не грех, грех нежелание учится.
Человек спросил, ему подсказали.
П.С. Я в школе плохо учился. Скучно было.
Человек спросил, ему подсказали.
П.С. Я в школе плохо учился. Скучно было.
- Сообщения: 26075
- Зарегистрирован: Пн фев 09, 2009 22:19:49
- Откуда: Когда-то был прекрасный город для людей
Неее, МК по Википедии учился.... Он и этого не знает...
Все мы, чего ни будь, да не знаем.
Форум для того и нужен, чтобы делится информацией, а не в школу отправлять:)
Форум для того и нужен, чтобы делится информацией, а не в школу отправлять:)
- Сообщения: 26075
- Зарегистрирован: Пн фев 09, 2009 22:19:49
- Откуда: Когда-то был прекрасный город для людей
Мне тут недавно одну принцессу пытались подсунуть прорепетировать по математике. Никак не может выучить таблицу умножения... Ни привелегированный лицей, ни четверо репетиторов ничего поделать не смогли...
И я сразу отказался, когда выяснил, что она не сможет выучить эту таблицу просто по той причине, что она не знает, что такое умножение.
Просто не знает. А так же не знает, что такое сложение. И не узнает, поскольку не знает, что такое числа.
И ЗНАТЬ НЕ ЖЕЛАЕТ, ПОТОМУ ЧТО ЕЕ ВЫСОЧЕСТВУ ЭТО НАФИГ НЕ НУЖНО !!!
Хотите с ней поделиться какой-нибудь информацией ?
И я сразу отказался, когда выяснил, что она не сможет выучить эту таблицу просто по той причине, что она не знает, что такое умножение.
Просто не знает. А так же не знает, что такое сложение. И не узнает, поскольку не знает, что такое числа.
И ЗНАТЬ НЕ ЖЕЛАЕТ, ПОТОМУ ЧТО ЕЕ ВЫСОЧЕСТВУ ЭТО НАФИГ НЕ НУЖНО !!!
Хотите с ней поделиться какой-нибудь информацией ?
Чего то меня тут в лоток я смотрю усиленно натыкать пытаются. Однако: я беру два ЦЕЛЫХ БЕЗЗНАКОВЫХ ЧИСЛА формата uint16_t, одно из которых основание, второе показатель. Допустим основание = 2, показатель = 2. По всей логике формула счастья квадрат числа это число умноженное само на себя и выглядит это следующим образом: 2*2=4. Просто и верно.
Теперь ардуина:
uint16_t a = 2;
uint16_t b = 2;
uint16_t c = pow(a,b); // результат равен 3
В чем проблема?
Теперь ардуина:
uint16_t a = 2;
uint16_t b = 2;
uint16_t c = pow(a,b); // результат равен 3
В чем проблема?
Не важно чем все начнется. Важно чем кончится!
- Сообщения: 12867
- Зарегистрирован: Сб дек 18, 2021 19:25:32
я же сказал. pow() оперирует числами с плавающей запятой. Подсовывайте хоть строки, хоть цвет - будет выполнено приведение к числам с плавающей запятой. Арифметические операции над такими числами отличаются от тех, каким Вас обучали в школе. Да и само число уже будет не то. В итоге получите результат 3.99999999999999999999999, что при приведении к целому даст 3.
Либо работайте с соответствующими типами, как аргументов, так и результата, либо учитывайте нюансы приведения-округления к целочисленным типам. Например, добавляйте 0.5
Либо работайте с соответствующими типами, как аргументов, так и результата, либо учитывайте нюансы приведения-округления к целочисленным типам. Например, добавляйте 0.5
Я тоже не знаю таблицы умножения. Но двузначные числа множу в уме существенно быстрее тех кто знаетМуркиз писал(а): Никак не может выучить таблицу умножения...
Многие ли с ходу смогут объяснить, что такое числа ?Муркиз писал(а): И не узнает, поскольку не знает, что такое числа.
Да и девицы, они про другое
Вроде все верно, но все же по правилам округления тут 4 должно быть, а не отсечение дробной... странно. Хотя я не спец по ардуиноMartian писал(а):я же сказал. pow() оперирует числами с плавающей запятой. Подсовывайте хоть строки, хоть цвет - будет выполнено приведение к числам с плавающей запятой. Арифметические операции над такими числами отличаются от тех, каким Вас обучали в школе. Да и само число уже будет не то. В итоге получите результат 3.99999999999999999999999, что при приведении к целому даст 3.
Добавлено after 16 minutes 20 seconds:
Re: Прошу помочь разобраться - кто хуже в школе учился я или МК?
Возможно, к результату стоит применить какую либо функцию преобразования ? Чтобы по правилам?
- Сообщения: 12867
- Зарегистрирован: Сб дек 18, 2021 19:25:32
Alexey1969, приведение к целочисленному типу, что и происходит у ТС, просто отбрасывает дробную часть. Вот если бы использовать округление, то тогда начнут работать правила всякие, а-ля к ближайшему целому, к меньшему, к большему и т.д.
[uquote="Viper_Snake",url="/forum/viewtopic.php?p=4379422#p4379422"]Чего то меня тут в лоток я смотрю усиленно натыкать пытаются.[/uquote]И правильно делают!
uint16_t a = 2;
uint16_t b = 2;
uint16_t c = pow(a,b);
delay(c);
и вот что ардуина 1.8.13 мне накомпилировала:
ldi r22, 0x04 ; 4
ldi r23, 0x00 ; 0
ldi r24, 0x00 ; 0
ldi r25, 0x00 ; 0
rcall .-1574 ; 0x1c6 <delay>
Только не говорите, что в r22 лежит тройка. И заметьте, ардуина не стала поручать вычисления контроллеру, а преобразовала их в константу. Похоже, проблема-то не в ардуине, а в вашем неумении ею пользоваться. Ошибиться в трёх строчках...
А при чём тут ардуина и при чём тут квадрат? Разве это она написала "pow(a,b)" ? Хотите квадрат? Тогда пишите 2*2. Хотите степень? Тогда не пишите 2*2. Степень — это ни разу не квадрат.квадрат числа это число умноженное само на себя и выглядит это следующим образом: 2*2=4. Просто и верно. Теперь ардуина:
uint16_t a = 2;
uint16_t b = 2;
uint16_t c = pow(a,b); // результат равен 3
Я не знаю, в чём у вас проблема, но вот только что добавил в в свой проект на атмеге48 три ваших строчки и заказал delay(c)В чем проблема?
uint16_t a = 2;
uint16_t b = 2;
uint16_t c = pow(a,b);
delay(c);
и вот что ардуина 1.8.13 мне накомпилировала:
ldi r22, 0x04 ; 4
ldi r23, 0x00 ; 0
ldi r24, 0x00 ; 0
ldi r25, 0x00 ; 0
rcall .-1574 ; 0x1c6 <delay>
Только не говорите, что в r22 лежит тройка. И заметьте, ардуина не стала поручать вычисления контроллеру, а преобразовала их в константу. Похоже, проблема-то не в ардуине, а в вашем неумении ею пользоваться. Ошибиться в трёх строчках...
Всего доброго.
Евгений.
Евгений.
- Сообщения: 26075
- Зарегистрирован: Пн фев 09, 2009 22:19:49
- Откуда: Когда-то был прекрасный город для людей
Проблема в том, что округление по умолчанию производится простым отбрасывание дробной части. И если вычисленный результат хоть 1 в десять в минус 16 степени меньше 4, то ответ будет все равно 3.
[uquote="Martian",url="/forum/viewtopic.php?p=4379426#p4379426"]я же сказал. pow() оперирует числами с плавающей запятой. Подсовывайте хоть строки, хоть цвет - будет выполнено приведение к числам с плавающей запятой. Арифметические операции над такими числами отличаются от тех, каким Вас обучали в школе. Да и само число уже будет не то. В итоге получите результат 3.99999999999999999999999, что при приведении к целому даст 3.
Либо работайте с соответствующими типами, как аргументов, так и результата, либо учитывайте нюансы приведения-округления к целочисленным типам. Например, добавляйте 0.5[/uquote]
Да это понятно, сама функция принимает как аргументы числа с плавающей запятой двойной точности. Дело не в том. Проблема в том, что мне нужно было всего лишь посчитать степени ЦЕЛЫХ ЧИСЕЛ. Речи о плавающей точке не было изначально, поэтому и удивился, что происходит такое округление - результат возведения в степень то принимает ЦЕЛОЧИСЛЕННАЯ переменная, естественно, если 2^2 функция pow считает как 3.99999 и так до бесконечности, после округления 4 мы никогда не получим. Но мне то нужна была работа с ЦЕЛЫМИ. Исходя из этого, если я не могу с помощью данной функции без костылей получить тот результат, который ожидается, имею полное право считать эту функцию ущербной. Никогда ею не пользовался, а тут потребовалось по быстрому бегущий огонек на трех регистрах сочинить для ребенка - решил его через степень двойки организовать от лени и на такие вилы напоролся. Программа примитивная до безобразия - считаем степень двойки от 0 до 23 и кормим три регистра результатом . Я даже delay в нее воткнул, ибо настолько все примитивно - казалось бы, ан нет - вилы с плавающей точкой приехали. И, прошу заметить, тот же инженерный калькулятор, при вводе целочисленных значений, целочисленные же и выдает, а не парит мозги с кучей девяток после запятой - наверное его создатели тоже в школе плохо учились...
Либо работайте с соответствующими типами, как аргументов, так и результата, либо учитывайте нюансы приведения-округления к целочисленным типам. Например, добавляйте 0.5[/uquote]
Да это понятно, сама функция принимает как аргументы числа с плавающей запятой двойной точности. Дело не в том. Проблема в том, что мне нужно было всего лишь посчитать степени ЦЕЛЫХ ЧИСЕЛ. Речи о плавающей точке не было изначально, поэтому и удивился, что происходит такое округление - результат возведения в степень то принимает ЦЕЛОЧИСЛЕННАЯ переменная, естественно, если 2^2 функция pow считает как 3.99999 и так до бесконечности, после округления 4 мы никогда не получим. Но мне то нужна была работа с ЦЕЛЫМИ. Исходя из этого, если я не могу с помощью данной функции без костылей получить тот результат, который ожидается, имею полное право считать эту функцию ущербной. Никогда ею не пользовался, а тут потребовалось по быстрому бегущий огонек на трех регистрах сочинить для ребенка - решил его через степень двойки организовать от лени и на такие вилы напоролся. Программа примитивная до безобразия - считаем степень двойки от 0 до 23 и кормим три регистра результатом . Я даже delay в нее воткнул, ибо настолько все примитивно - казалось бы, ан нет - вилы с плавающей точкой приехали. И, прошу заметить, тот же инженерный калькулятор, при вводе целочисленных значений, целочисленные же и выдает, а не парит мозги с кучей девяток после запятой - наверное его создатели тоже в школе плохо учились...
Не важно чем все начнется. Важно чем кончится!
[uquote="Viper_Snake",url="/forum/viewtopic.php?p=4379564#p4379564"]Проблема в том, что мне нужно было всего лишь посчитать степени ЦЕЛЫХ ЧИСЕЛ.[/uquote]Отнюдь! Проблема вовсе не в том. Вам вообще не нужно было считать степени. Никаких чисел. Бегущие огни делаются не на степенях, а на сдвиге.
P.S.: А ещё сдвиг влево — это сложение числа с самим собой. Поэтому для вычисления последовательных степеней двойки от нуля до, скажем, 24, надо (можно в цикле) складывать число само с собой. 1+1=2, 2+2=4, 4+4=8, 8+8=16 и т.д. ещё 20 раз. Это тоже одна машинная команда, но она неповоротлива (сдвигает только влево) как кувалда. А на процессорах 8080 ещё и тяжела как кувалда, ибо за один машинный цикл сдвигает сразу 16-разрядное число. Посему мне непонятно желание забивать гвозди не молотком, не кувалдой, а именно микроскопом... Это не похоже на лень. Это что-то другое.
Да не от лени, а от незнания! От того, что никогда не разрабатывали схем бегущих огней. Вот бы посмотреть на ваше возведение в степень на 155-й серии! Особенно, если основание, скажем, 3 или 5.потребовалось по быстрому бегущий огонек на трех регистрах сочинить для ребенка - решил его через степень двойки организовать от лени
Она не примитивна (до безобразия), а крива до того же самого безобразия! Это всё равно, что забивать гвозди микроскопом. Для забивания гвоздей есть же неубиваемый инструмент — молоток, то бишь сдвиг. В отличие от возведения в степень он работает хоть влево, хоть вправо, и выполняется за одну машинную команду (в отличие от даже целочисленной степени, которой нужно умножение), да пусть бы даже за 4 команды, если мы берём длинное целое на 32 бита, это всё равно быстрее умножения и тем паче возведения в степень. А ещё по ходу сдвига очень удобно подкидывать на приёмный вход очередные биты, вплоть до закольцовывания, как это делалось в многочисленных схемах бегущих огней в 80-е годы. Ваша самая главная ошибка была сделана на этапе алгоритмизации, и тут ни ардуина, ни какой-нибудь ещё язык программирования ни при чём. Тем более, что на поверку-то оказалось, что ардуина операцию pow(2,2) в целых числах считает как 4. Не 3 и не 5, а ровно 4. Зачем было применять float, если нужен был целочисленный результат?Программа примитивная до безобразия - считаем степень двойки от 0 до 23 и кормим три регистра результатом .
P.S.: А ещё сдвиг влево — это сложение числа с самим собой. Поэтому для вычисления последовательных степеней двойки от нуля до, скажем, 24, надо (можно в цикле) складывать число само с собой. 1+1=2, 2+2=4, 4+4=8, 8+8=16 и т.д. ещё 20 раз. Это тоже одна машинная команда, но она неповоротлива (сдвигает только влево) как кувалда. А на процессорах 8080 ещё и тяжела как кувалда, ибо за один машинный цикл сдвигает сразу 16-разрядное число. Посему мне непонятно желание забивать гвозди не молотком, не кувалдой, а именно микроскопом... Это не похоже на лень. Это что-то другое.
Всего доброго.
Евгений.
Евгений.
Блин, Женя, тебя не Краб часом покусал? Все тебе не то. А тебя не смутило ни разу, что для этой поделки еще и целая ардуина на 328 камне взята, когда тини 13 та же справилась бы без проблем, а еще 99,999999% времени тупо курила бездельничая. Я же написал, что все на сдвиге и сделал в итоге. Изначально было лениво, решил изъебнуться - результат удивил и обескуражил, поэтому и вопрос такой задал.Не пользовался я никогда этой функцией просто, а тут такой казус вышел. У этой задачи способов решения хренова туча, вплоть до перебора массива констант - дело то не в этом. Обработать переменную как надо и пнуть 3 байта через порт в сторону регистров это примитивная задача.
Добавлено after 5 minutes 45 seconds:
Re: Прошу помочь разобраться - кто хуже в школе учился я или МК?
И с чего ты вдруг решил, что я float использовал, если внезапно uint16_t был озвучен?
И, если не затруднит, продемонстрируйте пожалуйста код, в котором pow(2,2); без костылей результат 4 дает.
Добавлено after 5 minutes 45 seconds:
Re: Прошу помочь разобраться - кто хуже в школе учился я или МК?
И с чего ты вдруг решил, что я float использовал, если внезапно uint16_t был озвучен?
И, если не затруднит, продемонстрируйте пожалуйста код, в котором pow(2,2); без костылей результат 4 дает.
Не важно чем все начнется. Важно чем кончится!
- Сообщения: 12867
- Зарегистрирован: Сб дек 18, 2021 19:25:32
Нет. Эта функция изначально такая в Си. Просто надо как-то помнить язык, ну и в случае непонятных результатов всегда обращать в первую очередь внимание на типы. Сколько граблей поломано даже с простым знаковое-беззнаковое, когда по ошибке не то взято. А плавающая точка это всегда источник счастия...Viper_Snake писал(а):Исходя из этого, если я не могу с помощью данной функции без костылей получить тот результат, который ожидается, имею полное право считать эту функцию ущербной.


