Столкнулся с интересным феноменом, ковыряя ардуину со сдвиговым регистром 74HC595: встроенная в среду функция возведения в степень (pow()) работает на мой взгляд некорректно. Потребовалось мне двоечку в степень n возводить, а само число в виде переменной оформлено, которой разные целые значения присваиваются. Но прикол в том, что если например 2^0 или 2^1 считаются правильно, то все остальное на 1 меньше ожидаемого результата, то есть 2^2=3, 2^3=7, 2^4=15 и т.д. Помучался я с этим немного, плюнул, сделал все через битовый сдвиг, но осадочек остался. Может кто сталкивался с подобным поведением?
_________________ Не важно чем все начнется. Важно чем кончится!
тип аргументов pow() - с плавающей запятой. результат тоже .Приведение к целому вполне может сделать на 1 меньше.
Ну я так и понял - функция весьма кривая - как и все ардуиновское. Недавно хотел по быстрому с TM1628 разобраться используя библиотеки - исплевался от злости, а решения так и не нашел. Плюнул и внял способу RTFM - только после этого все получилось в лучшем виде. MAX5400 так же осваивал - под него вообще библиотек нет. Библиотеки это зло...
_________________ Не важно чем все начнется. Важно чем кончится!
Функция не кривая. У Вас неверное представление о машинных арифметических действиях с разными типами данных. Думаете, в других мк/языках/средах нет подобных нюансов? Ещё как есть. И библиотеки не зло.
Исходно, процессор кроме как складывать, вообще ничего не умеет
Не только процессор! Топикстартер тоже. Он, похоже, не знает, что возведение в (любую) степень делается через логарифм и экспоненту, а ожидает от МК лишь целочисленных умножений, суть многократных сложений. Плохо, видать, в школе учился...
Заголовок сообщения: Re: Прошу помочь разобраться - кто хуже в школе учился я или
Добавлено: Ср мар 01, 2023 14:42:54
Друг Кота
Карма: 107
Рейтинг сообщений: 3837
Зарегистрирован: Пн фев 09, 2009 22:19:49 Сообщений: 25236 Откуда: Когда-то был прекрасный город для людей
Рейтинг сообщения:0
Мне тут недавно одну принцессу пытались подсунуть прорепетировать по математике. Никак не может выучить таблицу умножения... Ни привелегированный лицей, ни четверо репетиторов ничего поделать не смогли...
И я сразу отказался, когда выяснил, что она не сможет выучить эту таблицу просто по той причине, что она не знает, что такое умножение. Просто не знает. А так же не знает, что такое сложение. И не узнает, поскольку не знает, что такое числа. И ЗНАТЬ НЕ ЖЕЛАЕТ, ПОТОМУ ЧТО ЕЕ ВЫСОЧЕСТВУ ЭТО НАФИГ НЕ НУЖНО !!!
Хотите с ней поделиться какой-нибудь информацией ?
Чего то меня тут в лоток я смотрю усиленно натыкать пытаются. Однако: я беру два ЦЕЛЫХ БЕЗЗНАКОВЫХ ЧИСЛА формата uint16_t, одно из которых основание, второе показатель. Допустим основание = 2, показатель = 2. По всей логике формула счастья квадрат числа это число умноженное само на себя и выглядит это следующим образом: 2*2=4. Просто и верно.
Теперь ардуина:
uint16_t a = 2; uint16_t b = 2;
uint16_t c = pow(a,b); // результат равен 3
В чем проблема?
_________________ Не важно чем все начнется. Важно чем кончится!
я же сказал. pow() оперирует числами с плавающей запятой. Подсовывайте хоть строки, хоть цвет - будет выполнено приведение к числам с плавающей запятой. Арифметические операции над такими числами отличаются от тех, каким Вас обучали в школе. Да и само число уже будет не то. В итоге получите результат 3.99999999999999999999999, что при приведении к целому даст 3. Либо работайте с соответствующими типами, как аргументов, так и результата, либо учитывайте нюансы приведения-округления к целочисленным типам. Например, добавляйте 0.5
Заголовок сообщения: Re: Прошу помочь разобраться - кто хуже в школе учился я или
Добавлено: Ср мар 01, 2023 16:36:10
Вымогатель припоя
Карма: 4
Рейтинг сообщений: 22
Зарегистрирован: Чт мар 05, 2009 05:31:16 Сообщений: 622 Откуда: г. Кемерово
Рейтинг сообщения:0
Муркиз писал(а):
Никак не может выучить таблицу умножения...
Я тоже не знаю таблицы умножения. Но двузначные числа множу в уме существенно быстрее тех кто знает
Муркиз писал(а):
И не узнает, поскольку не знает, что такое числа.
Многие ли с ходу смогут объяснить, что такое числа ?
Да и девицы, они про другое
Martian писал(а):
я же сказал. pow() оперирует числами с плавающей запятой. Подсовывайте хоть строки, хоть цвет - будет выполнено приведение к числам с плавающей запятой. Арифметические операции над такими числами отличаются от тех, каким Вас обучали в школе. Да и само число уже будет не то. В итоге получите результат 3.99999999999999999999999, что при приведении к целому даст 3.
Вроде все верно, но все же по правилам округления тут 4 должно быть, а не отсечение дробной... странно. Хотя я не спец по ардуино
Добавлено after 16 minutes 20 seconds: Re: Прошу помочь разобраться - кто хуже в школе учился я или МК? Возможно, к результату стоит применить какую либо функцию преобразования ? Чтобы по правилам?
Alexey1969, приведение к целочисленному типу, что и происходит у ТС, просто отбрасывает дробную часть. Вот если бы использовать округление, то тогда начнут работать правила всякие, а-ля к ближайшему целому, к меньшему, к большему и т.д.
Чего то меня тут в лоток я смотрю усиленно натыкать пытаются.
И правильно делают!
Цитата:
квадрат числа это число умноженное само на себя и выглядит это следующим образом: 2*2=4. Просто и верно. Теперь ардуина: uint16_t a = 2; uint16_t b = 2; uint16_t c = pow(a,b); // результат равен 3
А при чём тут ардуина и при чём тут квадрат? Разве это она написала "pow(a,b)" ? Хотите квадрат? Тогда пишите 2*2. Хотите степень? Тогда не пишите 2*2. Степень — это ни разу не квадрат.
Цитата:
В чем проблема?
Я не знаю, в чём у вас проблема, но вот только что добавил в в свой проект на атмеге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 лежит тройка. И заметьте, ардуина не стала поручать вычисления контроллеру, а преобразовала их в константу. Похоже, проблема-то не в ардуине, а в вашем неумении ею пользоваться. Ошибиться в трёх строчках...
Заголовок сообщения: Re: Прошу помочь разобраться - кто хуже в школе учился я или
Добавлено: Ср мар 01, 2023 17:19:48
Друг Кота
Карма: 107
Рейтинг сообщений: 3837
Зарегистрирован: Пн фев 09, 2009 22:19:49 Сообщений: 25236 Откуда: Когда-то был прекрасный город для людей
Рейтинг сообщения:0
Проблема в том, что округление по умолчанию производится простым отбрасывание дробной части. И если вычисленный результат хоть 1 в десять в минус 16 степени меньше 4, то ответ будет все равно 3.
я же сказал. pow() оперирует числами с плавающей запятой. Подсовывайте хоть строки, хоть цвет - будет выполнено приведение к числам с плавающей запятой. Арифметические операции над такими числами отличаются от тех, каким Вас обучали в школе. Да и само число уже будет не то. В итоге получите результат 3.99999999999999999999999, что при приведении к целому даст 3. Либо работайте с соответствующими типами, как аргументов, так и результата, либо учитывайте нюансы приведения-округления к целочисленным типам. Например, добавляйте 0.5
Да это понятно, сама функция принимает как аргументы числа с плавающей запятой двойной точности. Дело не в том. Проблема в том, что мне нужно было всего лишь посчитать степени ЦЕЛЫХ ЧИСЕЛ. Речи о плавающей точке не было изначально, поэтому и удивился, что происходит такое округление - результат возведения в степень то принимает ЦЕЛОЧИСЛЕННАЯ переменная, естественно, если 2^2 функция pow считает как 3.99999 и так до бесконечности, после округления 4 мы никогда не получим. Но мне то нужна была работа с ЦЕЛЫМИ. Исходя из этого, если я не могу с помощью данной функции без костылей получить тот результат, который ожидается, имею полное право считать эту функцию ущербной. Никогда ею не пользовался, а тут потребовалось по быстрому бегущий огонек на трех регистрах сочинить для ребенка - решил его через степень двойки организовать от лени и на такие вилы напоролся. Программа примитивная до безобразия - считаем степень двойки от 0 до 23 и кормим три регистра результатом . Я даже delay в нее воткнул, ибо настолько все примитивно - казалось бы, ан нет - вилы с плавающей точкой приехали. И, прошу заметить, тот же инженерный калькулятор, при вводе целочисленных значений, целочисленные же и выдает, а не парит мозги с кучей девяток после запятой - наверное его создатели тоже в школе плохо учились...
_________________ Не важно чем все начнется. Важно чем кончится!
Проблема в том, что мне нужно было всего лишь посчитать степени ЦЕЛЫХ ЧИСЕЛ.
Отнюдь! Проблема вовсе не в том. Вам вообще не нужно было считать степени. Никаких чисел. Бегущие огни делаются не на степенях, а на сдвиге.
Цитата:
потребовалось по быстрому бегущий огонек на трех регистрах сочинить для ребенка - решил его через степень двойки организовать от лени
Да не от лени, а от незнания! От того, что никогда не разрабатывали схем бегущих огней. Вот бы посмотреть на ваше возведение в степень на 155-й серии! Особенно, если основание, скажем, 3 или 5.
Цитата:
Программа примитивная до безобразия - считаем степень двойки от 0 до 23 и кормим три регистра результатом .
Она не примитивна (до безобразия), а крива до того же самого безобразия! Это всё равно, что забивать гвозди микроскопом. Для забивания гвоздей есть же неубиваемый инструмент — молоток, то бишь сдвиг. В отличие от возведения в степень он работает хоть влево, хоть вправо, и выполняется за одну машинную команду (в отличие от даже целочисленной степени, которой нужно умножение), да пусть бы даже за 4 команды, если мы берём длинное целое на 32 бита, это всё равно быстрее умножения и тем паче возведения в степень. А ещё по ходу сдвига очень удобно подкидывать на приёмный вход очередные биты, вплоть до закольцовывания, как это делалось в многочисленных схемах бегущих огней в 80-е годы. Ваша самая главная ошибка была сделана на этапе алгоритмизации, и тут ни ардуина, ни какой-нибудь ещё язык программирования ни при чём. Тем более, что на поверку-то оказалось, что ардуина операцию pow(2,2) в целых числах считает как 4. Не 3 и не 5, а ровно 4. Зачем было применять float, если нужен был целочисленный результат?
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 дает.
_________________ Не важно чем все начнется. Важно чем кончится!
Исходя из этого, если я не могу с помощью данной функции без костылей получить тот результат, который ожидается, имею полное право считать эту функцию ущербной.
Нет. Эта функция изначально такая в Си. Просто надо как-то помнить язык, ну и в случае непонятных результатов всегда обращать в первую очередь внимание на типы. Сколько граблей поломано даже с простым знаковое-беззнаковое, когда по ошибке не то взято. А плавающая точка это всегда источник счастия...
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения