Т.е. каждый раз сравнивают (проверяют), что разность больше чем вычитаемое, тогда продолжают вычитать. Накапливают переменную. и так далее с каждым разрядом?
Нескольно простых вопросов о программировании AVR на Си.
[uquote="Starichok51",url="/forum/viewtopic.php?p=4386512#p4386512"]кроме деления часто используют вычитание.[/uquote]
Т.е. каждый раз сравнивают (проверяют), что разность больше чем вычитаемое, тогда продолжают вычитать. Накапливают переменную. и так далее с каждым разрядом?
Т.е. каждый раз сравнивают (проверяют), что разность больше чем вычитаемое, тогда продолжают вычитать. Накапливают переменную. и так далее с каждым разрядом?
Станислав
- Реклама
[uquote="СКАЗОЧНИК",url="/forum/viewtopic.php?p=4386503#p4386503"]Понимаю, что надо использовать деление на 10 и остаток от деления на 10. Много чего уже посмотрел, но все равно плохо доходит.[/uquote]Так ведь Eddy_Em в Сообщении от Вт ноя 22, 2022 11:07:19 на предыдущей странице уже всё расписал!
А какая разница, сколько их? Изначально буфер на 5 символов надо заполнить пробелами или каким другим пустым кодом, если кодировка не ASCII. Цифры же формируются с конца (обратите внимание на --bufptr у Eddy_Em), и этот цикл заканчивается не по счётчику, а по нулевому остатку от исходного числа. При этом сколько символов сформировалось, столько и ладно. Программа даже не заморачивается подсчётом этих символов!Суть в том, что я не знаю, сколько разрядов у числа изначально. Может быть три, а может пять.
AVR Application Note 204: BCD Arithmetics. Начинается этот аппноут как раз с программы, а точнее с алгоритма Binary 16 to BCD Conversion. А хорошее разъяснение всей этой математики есть в 3-м томе 4-томника "Микроконтроллеры" от Алекса Фрунзе. Не столь популярное, но тоже небесполезное описание всё той же самой математики есть и в жёлтой книжке "Программы для микропроцессоров" Гуртовцева и Гудыменко. И всё это есть в сети.Опишите суть, или ткните, где это максимально понятно расписано.
Всего доброго.
Евгений.
Евгений.
[uquote="СКАЗОЧНИК",url="/forum/viewtopic.php?p=4386503#p4386503"]...Теперь я хочу разбивать число неопределенного количества разрядов на цифры... Суть в том, что я не знаю, сколько разрядов у числа изначально...[/uquote]
Не обязательно делить или вычитать. Можно провести десятичную коррекцию, начиная с младших разрядов.
https://radiokot.ru/forum/viewtopic.php ... 9#p1417529
Не обязательно делить или вычитать. Можно провести десятичную коррекцию, начиная с младших разрядов.
https://radiokot.ru/forum/viewtopic.php ... 9#p1417529
В древности писал статью на тему вывода чисел: http://arv.radioliga.com/content/view/106/49/
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
да, каждый раз нужно сначала делать проверку на возможность вычесть, потом вычитают.СКАЗОЧНИК писал(а):Т.е. каждый раз сравнивают (проверяют), что разность больше чем вычитаемое, тогда продолжают вычитать. Накапливают переменную. и так далее с каждым разрядом?
а иногда делают наоборот - сначала вычитают, потом проверяют остаток на знак. если положительный, продолжают вычитать. если отрицательный, прибавляют и переходят к следующему разряду.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
- Реклама
Starichok51, спасибо, интересно. Код небольшой (против /10 и %10).
---
Да, но медленнее
.
Код выше по сравнению с кодом ниже: 20 µs / 4 µs (ATmega328, 16 MHz).
Код: Выделить всё
int16_t data = 9876;
---
while ((data - 1000) > 0) {
data -= 1000;
a++;
}
while ((data - 100) > 0) {
data -= 100;
b++;
}
while ((data - 10) > 0) {
data -= 10;
c++;
}
d = data;
---
результат:
9876
9 8 7 6
Да, но медленнее
Код выше по сравнению с кодом ниже: 20 µs / 4 µs (ATmega328, 16 MHz).
Код: Выделить всё
a = data / 1000;
b = (data / 100) % 10;
c = (data / 10) % 10;
d = data % 10;veso74, что-то мне не верится, что деление и потом взятие %10 работает быстрее вычитания.
я не умею писать для МК на Си, чтобы самому это проверить.
я не умею писать для МК на Си, чтобы самому это проверить.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Все по умолчанию, оптимизация на макс. Ардуино IDE, со своим языком и функциями (печать в Serial из отчетности время пропущен).
[uquote="Starichok51",url="/forum/viewtopic.php?p=4386703#p4386703"]veso74, что-то мне не верится, что деление и потом взятие %10 работает быстрее вычитания.
я не умею писать для МК на Си, чтобы самому это проверить.[/uquote]
Поверьте, быстрее.
Компиляторы сейчас умные, и при включенной (по умолчанию) оптимизации сами реализуют деление на 10 как умножение со сдвигом, что и кода меньше занимает, и по времени гораздо быстрее, чем отнимать и считать циклы.
К примеру, вместо целочисленного деления uint8_t числа на 10 компилятор сам может сообразить, что это то же самое, что умножить это число на 205 и результат сдвинуть на 11 разрядов вправо.
Почему 205? Потому что X / 10 = X * 204.8 / 2048 ~= X * 205 / 2048 = (X * 205) << 11. Что для любых чисел само по себе приблизительно, но для однобайтовых X погрешность нулевая.
я не умею писать для МК на Си, чтобы самому это проверить.[/uquote]
Поверьте, быстрее.
Компиляторы сейчас умные, и при включенной (по умолчанию) оптимизации сами реализуют деление на 10 как умножение со сдвигом, что и кода меньше занимает, и по времени гораздо быстрее, чем отнимать и считать циклы.
К примеру, вместо целочисленного деления uint8_t числа на 10 компилятор сам может сообразить, что это то же самое, что умножить это число на 205 и результат сдвинуть на 11 разрядов вправо.
Почему 205? Потому что X / 10 = X * 204.8 / 2048 ~= X * 205 / 2048 = (X * 205) << 11. Что для любых чисел само по себе приблизительно, но для однобайтовых X погрешность нулевая.
- Сообщения: 1405
- Зарегистрирован: Вт июн 07, 2011 08:03:18
+1000500. Считаю, и не только я, что в наше время, в первую очередь, нужно обращать внимание на наглядность исходного текста, а не заниматься "оптимизацией". Все эти оптимизации ушли вместе с ассемблером.
WiseLord, а если число большое и нужно поделить на 10 тысяч или на 10 миллионов?
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
https://radiokot.ru/forum/viewtopic.php ... 7#p4386697
Тестирование некорректное. Если data - константа, компилятор имеет полное право вместо
записать a = 9; b = 8; c = 7; d = 6;
И МК вообще ничего не будет вычислять.
Кроме того, в коде с циклами три ошибки. Но это так, мелочи.
Тестирование некорректное. Если data - константа, компилятор имеет полное право вместо
Код: Выделить всё
data = 9876;
a = data / 1000;
b = (data / 100) % 10;
c = (data / 10) % 10;
d = data % 10;И МК вообще ничего не будет вычислять.
Кроме того, в коде с циклами три ошибки. Но это так, мелочи.
[uquote="Starichok51",url="/forum/viewtopic.php?p=4386819#p4386819"]WiseLord, а если число большое и нужно поделить на 10 тысяч или на 10 миллионов?[/uquote]Принцип остаётся тот же - заменить деление на умножение и сдвиг.
Если контроллер умеет аппаратно умножить два 8бит числа с 16бит результатом, то и умножение чисел с большей разрядностью легко сводится к умножению октет и суммироованию, что всё равно обходится дешевле циклов вычитаний.
Если контроллер умеет аппаратно умножить два 8бит числа с 16бит результатом, то и умножение чисел с большей разрядностью легко сводится к умножению октет и суммироованию, что всё равно обходится дешевле циклов вычитаний.
МК вычисляет
И еще хочет :ПП
36..40 µs
Код: Выделить всё
uint64_t data = 11126789012;
---
data++;
PORTB = data / 123456789;Добавлю: встроенная функция avr-gcc позволяет иметь остаток от деления одновременно с получением частного. Т.е. не сначала деление, а потом взятие остатка от деления, а за один вызов. Думаю, оптимизатор распознает эту ситуацию и делает с минимальными затратами.
Если честно, то вообще не понимаю, к чему в данной ситуации погоня за тактами... Индикация - процесс настолько низкоприоритетный и медленный, что экономить на нем просто глупо...
Если честно, то вообще не понимаю, к чему в данной ситуации погоня за тактами... Индикация - процесс настолько низкоприоритетный и медленный, что экономить на нем просто глупо...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
mont-oriol, да, компилятор считает один раз. С расчетом в цикле изменилось: 24 µs к 72 µs. Нравится, есть где использовать.
А лично в 99% случаев неважно как написано - от этого ничего не зависит (скорость?), и если память будет на пределе (если, конечно не любимый ATtiny13A). Вопрос ради вопроса.
А лично в 99% случаев неважно как написано - от этого ничего не зависит (скорость?), и если память будет на пределе (если, конечно не любимый ATtiny13A). Вопрос ради вопроса.
[uquote="ARV",url="/forum/viewtopic.php?p=4386677#p4386677"]В древности писал статью на тему вывода чисел: http://arv.radioliga.com/content/view/106/49/[/uquote]
Очень понравилась Ваша реализация. ) Переделал чуток под себя, конечно.
Идеально выводит числа на 6 разрядов индикатора, прям как я хотел.
Спасибо.
Добавлено after 2 minutes:
З.Ы. да и пришлось про свитч-кейс еще почитать, что он умеет не только с целыми числами работать, но и с символами.
Очень понравилась Ваша реализация. ) Переделал чуток под себя, конечно.
Идеально выводит числа на 6 разрядов индикатора, прям как я хотел.
Спасибо.
Добавлено after 2 minutes:
З.Ы. да и пришлось про свитч-кейс еще почитать, что он умеет не только с целыми числами работать, но и с символами.
Станислав
- Сообщения: 204
- Зарегистрирован: Сб июл 30, 2011 21:00:24
[uquote="Just_Fluffy",url="/forum/viewtopic.php?p=4324348#p4324348"]ARV
И если критична производительность и/или объем кода - то стоит задуматься, а нужен ли тут float ?
Вспомнила, делался какой то показометр на линейке диодов, там логарифмическое что то просили считать. Пришлось туда втулить.[/uquote]
А если некритичны производительность и/или объем кода – то тоже стоит задуматься, а нужен ли тут float?
Как я понял из последней фразы, из-за логарифма вы «втулили» float.
Так в целочисленной арифметике тоже есть логарифм.
Например, в, условно говоря, хорошем ассемблере есть вызов функции логарифма. Одна строчка - и есть готовый логарифм.
По объёму и скорости выполнения программа наверняка будет лучше.
Скорее всего, подойдёт самый простой вариант, где аргумент – 2 байта. У него точность вроде как полпроцента, вполне достаточно для рядовых целей.
Диапазон, правда, небольшой, но, скорее всего, несложно расширить с помощью простой школьной арифметики.
И если критична производительность и/или объем кода - то стоит задуматься, а нужен ли тут float ?
Вспомнила, делался какой то показометр на линейке диодов, там логарифмическое что то просили считать. Пришлось туда втулить.[/uquote]
А если некритичны производительность и/или объем кода – то тоже стоит задуматься, а нужен ли тут float?
Как я понял из последней фразы, из-за логарифма вы «втулили» float.
Так в целочисленной арифметике тоже есть логарифм.
Например, в, условно говоря, хорошем ассемблере есть вызов функции логарифма. Одна строчка - и есть готовый логарифм.
По объёму и скорости выполнения программа наверняка будет лучше.
Скорее всего, подойдёт самый простой вариант, где аргумент – 2 байта. У него точность вроде как полпроцента, вполне достаточно для рядовых целей.
Диапазон, правда, небольшой, но, скорее всего, несложно расширить с помощью простой школьной арифметики.
- Сообщения: 547
- Зарегистрирован: Ср июн 29, 2022 16:25:45
AQ29, Вам шашечки или ехать?
Суть была в чем - пихать флоаты налево и направо - не стоит. В большинстве (обратите внимание - не всегда) случаев от флоатов можно отказаться. Но иногда с ними проще.
У меня проектов на мелких МК с флоатами - ну вот только один и вспомнился. В остальных случаях получилось уйти к целочисленной математике. Ну там, где вообще надо было к ней уходить.
Касательно флоата и логарифма.
Это заказной проект был. Не особо дорогой. И тратить свое время на какие то изыски - не выгодно было.
Я отдавала себе отчет, что флоаты на авр - не самое лучшее решение...
Но в данном случае ресурсов хватало и таймингов тоже. Зачем мне искать/придумывать ассемблерный вариант или целочисленный алгоритм?
Что бы процессор в idle крутился не 40, а 60% времени? Или что бы свободного флеша у меня оставалось не 30, а 50% ?
Куда мне девать эти такты и килобайты? Солить на зиму?
Поэтому проще и быстрее взять флоатный логарифм (заодно не трахаться с пересчетом дробных коэффициентов, участвующих в расчетах, в целочисленные) и получить на выходе нужное мне число. Которое потом округлится в целочисленную переменную и засветится на шкале.
Управление двумя линейками диодов было сделано из таймерного прерывания, чтение полученных извне данных - там же. Заодно в том же таймерном прерывании еще и АЦП опрашивался и перезапускался. И его данные в массив для усреднения складывались...
Всё остальное процессорное время - в моем распоряжении..... И его для той задачи - много. Там можно считать что угодно, хоть float-ом, хоть double-ом... Подождать флаг прихода данных или обновления АЦП -пересчитать данные и обновить инфу для диодов..
Программа в восьмую мегу поместилась, около 30% флеша свободно осталось, в ТЗ по таймингам - умещалось с запасом.
А, и еще не надо спорить с заказчиком. Им надо было, что б все было точно-точно... Дали ТЗ с формулами - получили результат. Я получила денешшшшку. И все довольны.
Зачем мне тратить свое время в таком случае на придумывание?...
Суть была в чем - пихать флоаты налево и направо - не стоит. В большинстве (обратите внимание - не всегда) случаев от флоатов можно отказаться. Но иногда с ними проще.
У меня проектов на мелких МК с флоатами - ну вот только один и вспомнился. В остальных случаях получилось уйти к целочисленной математике. Ну там, где вообще надо было к ней уходить.
Касательно флоата и логарифма.
Это заказной проект был. Не особо дорогой. И тратить свое время на какие то изыски - не выгодно было.
Я отдавала себе отчет, что флоаты на авр - не самое лучшее решение...
Но в данном случае ресурсов хватало и таймингов тоже. Зачем мне искать/придумывать ассемблерный вариант или целочисленный алгоритм?
Что бы процессор в idle крутился не 40, а 60% времени? Или что бы свободного флеша у меня оставалось не 30, а 50% ?
Куда мне девать эти такты и килобайты? Солить на зиму?
Поэтому проще и быстрее взять флоатный логарифм (заодно не трахаться с пересчетом дробных коэффициентов, участвующих в расчетах, в целочисленные) и получить на выходе нужное мне число. Которое потом округлится в целочисленную переменную и засветится на шкале.
Управление двумя линейками диодов было сделано из таймерного прерывания, чтение полученных извне данных - там же. Заодно в том же таймерном прерывании еще и АЦП опрашивался и перезапускался. И его данные в массив для усреднения складывались...
Всё остальное процессорное время - в моем распоряжении..... И его для той задачи - много. Там можно считать что угодно, хоть float-ом, хоть double-ом... Подождать флаг прихода данных или обновления АЦП -пересчитать данные и обновить инфу для диодов..
Программа в восьмую мегу поместилась, около 30% флеша свободно осталось, в ТЗ по таймингам - умещалось с запасом.
А, и еще не надо спорить с заказчиком. Им надо было, что б все было точно-точно... Дали ТЗ с формулами - получили результат. Я получила денешшшшку. И все довольны.
Зачем мне тратить свое время в таком случае на придумывание?...
Белая и Пушистая
Я не ИИ, поэтому могу ошибаться.
Я не ИИ, поэтому могу ошибаться.
[uquote="Just_Fluffy",url="/forum/viewtopic.php?p=4387329#p4387329"]в данном случае ресурсов хватало и таймингов тоже. Зачем мне искать/придумывать ассемблерный вариант или целочисленный алгоритм? Что бы процессор в idle крутился не 40, а 60% времени? Или что бы свободного флеша у меня оставалось не 30, а 50% ? Куда мне девать эти такты и килобайты? Солить на зиму?[/uquote]Вот, кстати, согласен на все 146%.

Аналогичную задачу я решал (и решил) на 13-й тиньке, но (оффтопик!) на ассемблере, поскольку из прикидок на ардуине мне показалось, что на С, да ещё с логарифмом в плавающей запятой я в мелкую тиньку не уложусь: размер кода для 48-й атмеги даже без плавающей запятой был 1864 байта. На асме, конечно, уложился. Объём прошивки стал 760 байт, быстродействие упёрлось в АЦП, а не в процессор, и возник тот же самый вопрос: куда девать лишние такты и лишние байты (25% памяти)???Управление двумя линейками диодов было сделано из таймерного прерывания, чтение полученных извне данных - там же. Заодно в том же таймерном прерывании еще и АЦП опрашивался и перезапускался. И его данные в массив для усреднения складывались...
Абсолютно справедливая постановка вопроса, ибо никогда не надо забывать про критерий разумной достаточности.Зачем мне тратить свое время в таком случае на придумывание?...
Всего доброго.
Евгений.
Евгений.


