23:59
long double спасает мир
Дважды за день попался на "детских" ошибках с вычислениями.
Надо было перенести вычислительный алгоритм с компа в микроконтроллер.
1. Я был предупреждён, что в PIC32 типы float и double эквивалентны. Если хочешь получить что-то побольше, чем 32 бита, надо писать long double. Поэтому я решил -- а, пофиг, напишу float. Алгоритм заработал, но в одном месте показывал смещённые результаты. Причём чем дальше, тем больше было смещение. Да, это набегала ошибка при проведении повторяющихся операций (сложения). Написал long double, заработало.
2. В другом месте решил, что чтобы было поточнее, буду пока есть возможность проводить вычисления с целыми числами. Там было умножение. Я перемножил два инта. А потом смотрю, чего это у меня результаты вычислений не зависят ни от чего вообще. Что ни делаю, получаю 0.5 повторяемо (после всех других вычислений). Эти инты содержали в себе результаты считывания с 18-битного АЦП. А произведение двух 18-битных чисел это 36-битное число. Оно не влезало в 32-битную разрядную сетку. У меня постоянно возникало переполнение. Стал эти числа приводить к long double ещё до умножения. Сразу всё стало правильно.
Надо было перенести вычислительный алгоритм с компа в микроконтроллер.
1. Я был предупреждён, что в PIC32 типы float и double эквивалентны. Если хочешь получить что-то побольше, чем 32 бита, надо писать long double. Поэтому я решил -- а, пофиг, напишу float. Алгоритм заработал, но в одном месте показывал смещённые результаты. Причём чем дальше, тем больше было смещение. Да, это набегала ошибка при проведении повторяющихся операций (сложения). Написал long double, заработало.
2. В другом месте решил, что чтобы было поточнее, буду пока есть возможность проводить вычисления с целыми числами. Там было умножение. Я перемножил два инта. А потом смотрю, чего это у меня результаты вычислений не зависят ни от чего вообще. Что ни делаю, получаю 0.5 повторяемо (после всех других вычислений). Эти инты содержали в себе результаты считывания с 18-битного АЦП. А произведение двух 18-битных чисел это 36-битное число. Оно не влезало в 32-битную разрядную сетку. У меня постоянно возникало переполнение. Стал эти числа приводить к long double ещё до умножения. Сразу всё стало правильно.
13.08.2020 в 04:03
13.08.2020 в 08:59
13.08.2020 в 11:44
И при этом не генерилась ошибка?
13.08.2020 в 12:04
13.08.2020 в 19:10
или эта версия gcc это не поддерживает?
13.08.2020 в 19:41
и что именно он поддерживает аппаратно?
а что вообще пик32 умеет?
он хотя бы целочисленное умножение 32х32=64 умеет?
а целочисленное деление?
16.08.2020 в 13:33
Поддерживает работу с типами с плавающей точкой длиной 32 и 64 бита. 80 бит, видимо, не поддерживает. Какие операции конкретно пока выяснить не удалось.
Умножение и деление целочисленное, в том числе 32*32=>64 умеет. Для этого в процессоре существует отдельный блок. Результат записывается в специальные два регистра, для этого предназначенные. По-видимому, умножение и деление не работает в один такт, т.к. указано, что пока умножитель/делитель работает могут выполняться иные операции. Но сколько операция выполняется, пока выяснить не удалось.
В документации на пик32 отсутствует система команд, присутствуют только отсылки на стандартную архитектуру MIPS32 release 2.