покритикуйте алгоритм разбора числа
- Войдите на сайт для отправки комментариев
Пт, 19/01/2018 - 23:40
в обще на основе библиотеки LedControl.h подлючил 8 разрядный 7 сигментный дисплей через МАХ7221
но в сети так и не нашел адекватного алгоритма вывода на него произвольного числа с плавующей точкой, поэтому написал свой
//честно гуглил 3 дня
//и да, ардуиной я 1ю неделю занимаюсь, опята 0, знаний не много успел изучить
итак код
/*--------------------------- разложение число (точность 1/100)---------------------------*/
/*float numbers число с точкой*/
numbers = 710;
float tmp = abs(numbers); // модуль числа
long disp_c; // Переменная для целых чисел
int disp_d; // Переменная для дробной части числа (нужна точность 2 знака всего)
disp_c = long(tmp); // целая часть числа
int mn = 0; // число дробных знаков (счетчик)
long j=0;int count_c=0;
j=disp_c;
for (int i=1; i<=8; i=i+1){ if (j<10){count_c=i; /*Serial.println(count_c);*/ break;} else { j = j/10; } } //count_c = длинне целой части числа
/*--------------------------- вывод на экран ---------------------------*/
lc.clearDisplay(0); //очищаю
disp_d = (tmp-disp_c)*100;
if (disp_d>0){//есть дробная часть, вывожу её в 1 или 2 правых регистра
if (disp_d<10) { lc.setDigit(0, 0, byte(disp_d), 0); mn=1; } else { lc.setDigit(0, 1, byte(disp_d/10), 0); lc.setDigit(0, 0, byte(disp_d-(disp_d/10*10)), 0); mn=2; }
}
int celoe[8]; //массив для хранения целой части по символьно
// разбираю число на знаки
celoe[0] = (disp_c % 10) / 1;
celoe[1] = (disp_c % 100) / 10;
celoe[2] = (disp_c % 1000) / 100;
celoe[3] = (disp_c % 10000) / 1000;
celoe[4] = (disp_c % 100000) / 10000;
celoe[5] = (disp_c % 1000000) / 100000;
celoe[6] = (disp_c % 10000000) / 1000000;
celoe[7] = (disp_c % 100000000) / 10000000;
int bl = 1; //временная переменная указать на точку
for (int i=0; i<count_c; i++){ //вывод на экран из массива символы
lc.setDigit(0, i+mn, byte(celoe[i]), bl);
bl=0;
// Serial.println(disp_c);
}
единственное не успел доделать вывод знака "-" для отрицательных значений
покритикуйте, может я чтото сделал не оптимально ... или даже не верно ... или чтото можно заменить на более простые конструкции...
//честно гуглил 3 дня
void setup() { Serial.begin(9600); float num=12.34; Serial.print(num); } void loop() { }я привел только часть кода, где идет самое разложение и вывод на экран
интересно, к чему мы 2 дня обсуждали циклы, если опять каждый разряд целого считается своим оператором?
unsigned long pow10[9]; void setup { pow10[0] =1; for (i=1; i<9; i++) { pow10[i] = pow10[i-1]*10; } } void loop { for (i=0; i<8; i++) { celoe[i] = (disp_c % pow10[i+1]) / pow10[i]; } }значит так
void setup { pow10[0] =1; for (int i=1; i<9; i++) { pow10[i] = pow10[i-1]*10; } .... void loop { ....... ....... /*--------------------------- разложение число (точность 1/100)---------------------------*/ /*float numbers число с точкой*/ numbers = 35710.4526; float tmp = abs(numbers); // модуль числа long disp_c; // Переменная для целых чисел int disp_d; // Переменная для дробной части числа (нужна точность 2 знака всего) disp_c = long(tmp); // целая часть числа int mn = 0; // число дробных знаков (счетчик) long j=0;int count_c=0; j=disp_c; for (int i=1; i<=8; i=i+1){ if (j<10){count_c=i; /*Serial.println(count_c);*/ break;} else { j = j/10; } } //count_c = длинне целой части числа /*--------------------------- вывод на экран ---------------------------*/ lc.clearDisplay(0); //очищаю disp_d = (tmp-disp_c)*100; if (disp_d>0){//есть дробная часть, вывожу её в 1 или 2 правых регистра if (disp_d<10) { lc.setDigit(0, 0, byte(disp_d), 0); mn=1; } else { lc.setDigit(0, 1, byte(disp_d/10), 0); lc.setDigit(0, 0, byte(disp_d-(disp_d/10*10)), 0); mn=2; } } int celoe[8]; //массив для хранения целой части по символьно // разбираю число на знаки for (int i=0; i<=count_c; i++) { celoe[i] = (disp_c % pow10[i+1]) / pow10[i];} /* celoe[0] = (disp_c % 10) / 1; celoe[1] = (disp_c % 100) / 10; celoe[2] = (disp_c % 1000) / 100; celoe[3] = (disp_c % 10000) / 1000; celoe[4] = (disp_c % 100000) / 10000; celoe[5] = (disp_c % 1000000) / 100000; celoe[6] = (disp_c % 10000000) / 1000000; celoe[7] = (disp_c % 100000000) / 10000000; */ int bl = 1; //временная переменная указать на точку for (int i=0; i<count_c; i++){ //вывод на экран из массива символы lc.setDigit(0, i+mn, byte(celoe[i]), bl); bl=0; // Serial.println(disp_c); } }сорри, в циклах переменную-итератор i забыл обьявить, исправьте
А зачем вообще тянуть сюда float?
итератор добавил
а как иначе? - разбирать через строку? но разве ардуино умеет со строками работать? (точнее разве это не будет слишком ресурсоемко для этого)
Что-то автор и мне голову заморочил. Зачем вообще степени десятки нужны? Кто мешает сделать так:
for (int i=0; i<8; i++) { celoe[i] = (disp_c % 10); disp_c =/10; }Что-то автор и мне голову заморочил. Зачем вообще степени десятки нужны? Кто мешает сделать так:
for (int i=0; i<8; i++) { celoe[i] = (disp_c % 10); disp_c =/10; }я так пробовал, но у меня при 6-8 значных числах по непонятной причине вылезает погрешность на 1-2 последних знаках...
поэтому отложил и на другой алгоритм перешел, который дал стабильный результат на выходе
тоесть 87654321 могут выдать то 98765423 то 98765415
disp_c =/10; илиdisp_c /= 10; https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/division-assignment-operatorитого выходит так?
void loop { ....... ....... /*--------------------------- разложение число (точность 1/100)---------------------------*/ /*float numbers число с точкой*/ numbers = 35710.4526; //число для теста float tmp = abs(numbers); // модуль числа long disp_c; // Переменная для целых чисел int disp_d; // Переменная для дробной части числа (нужна точность 2 знака всего) disp_c = long(tmp); // целая часть числа int mn = 0; // число дробных знаков (счетчик) long j=0;int count_c=0; j=disp_c; for (int i=1; i<=8; i=i+1){ if (j<10){count_c=i; /*Serial.println(count_c);*/ break;} else { j = j/10; } } //count_c = длинне целой части числа /*--------------------------- вывод на экран ---------------------------*/ lc.clearDisplay(0); //очищаю disp_d = (tmp-disp_c)*100; if (disp_d>0){//есть дробная часть, вывожу её в 1 или 2 правых регистра if (disp_d<10) { lc.setDigit(0, 0, byte(disp_d), 0); mn=1; } else { lc.setDigit(0, 1, byte(disp_d/10), 0); lc.setDigit(0, 0, byte(disp_d-(disp_d/10*10)), 0); mn=2; } } int celoe[8]; //массив для хранения целой части по символьно // разбираю число на знаки for (int i=0; i<=count_c; i++) { celoe[i] = (disp_c % 10); disp_c /= 10; } int bl = 1; //временная переменная указать на точку for (int i=0; i<count_c; i++){ //вывод на экран из массива символы lc.setDigit(0, i+mn, byte(celoe[i]), bl); bl=0; } }я так пробовал, но у меня при 6-8 значных числах по непонятной причине вылезает погрешность на 1-2 последних знаках...
Откуда там погрешность?
Вот, пробую
for (int i=0; i<8; i++) { celoe[i] = (disp_c % 10); disp_c /=10; } Вывод: Number = 12345678 celoe[0] = 8 celoe[1] = 7 celoe[2] = 6 celoe[3] = 5 celoe[4] = 4 celoe[5] = 3 celoe[6] = 2 celoe[7] = 1disp_c =/10; илиdisp_c /= 10;да спасибо, никак не могу запомнить, всегда ориентируюсь на диагностику компилятора :)
да, я пробовал с флоатом - видимо от него была
а с лонгом всё норм
да, я пробовал с флоатом - видимо от него была
а с лонгом всё норм
Семен Семеныч :)
Целочисленное деление от точного догадываетесь чем отличается?
Целочисленное деление от точного догадываетесь чем отличается?
Я в непонятках.
Объясните, если не трудно.
итак эту часто оптимизировали, а остальное можно както еще сократить и оптимизировать?
вообще я хотел бы вообще отказаться от библиотеки - там есть лишний код, который не нужен попросту (для работы с матрицами)
но чтото мне не хватает пока знанеий переписать все для прямой работы и чтобы несколько экранок цепочкой собирать...
Цель автора обойтись без ftoa(), или он просто о ней не знает?
The dtostrf() function converts the double value passed in
valinto an ASCII representationthat will be stored unders. The caller is responsible for providing sufficient storage ins.Conversion is done in the format
"[-]d.ddd". The minimum field width of the output string (including the possible'.' and the possible sign for negative values) is given inwidth, andprecdetermines the number of digits after the decimal sign.widthis signed value, negative for left adjustment.The dtostrf() function returns the pointer to the converted string
s.================================================
Это ж ад какой-то! Ну нельзя заниматься программированием, если родился с синдромом Дауна!
Это гнусная дискриминация инвалидов! Вам должно быть стыдно!
Ещё и по-ненашему процитировали! Чтобы поиздеваться? Вам разве неизвестно, что по новым правилам задания ЕГЭ полагается зачитывать вслух, чтобы не было дискриминации неумеющих читать?
А по сути Вашего "решения", ТС уже дано нас всех просветил, что
разве ардуино умеет со строками работать?
После такого заявления, я сразу понял, что это у меня синдром дауна :( и ушёл из темы :))))
и ушёл из темы :))))
Same shit!
не все люди - ботаны сишники. и просьба свои умозаключения на эту тему держать при себе
я честно сказал - ардуиной первую неделю занимаюсь, а язык С и его вариации вообще не признаю как адекватный язык - он навязан мелкомягкими для воплощения своих планов по захвату мира.
если по моему вопросу вы знаете, как чтото сделать - то пишите - что и так, а не хотите делится этим (а быстрее всего сами не знаете попросту) - тогда вообще ничего не пишите - умнее в глазах других будете выглядеть.
язык С и его вариации вообще не признаю как адекватный язык - он навязан мелкомягкими для воплощения своих планов по захвату мира.
Враки.
Тогда, в начале Сишных времён, никаких мелкомягких не было.
А мелкомяхкие сделали свой ублюдочный Quick C в 1990 или 1992-м году.
ардуиной первую неделю занимаюсь
И сразу "памагите!!!" - хоть бы пару месяцев позанимался.
язык С и его вариации вообще не признаю как адекватный язык
оставьте это для Вашей истории болезни.
Характер вопросов, которые Вы задаёте говорит не о незнении языкка, а об отстутствии каких бы то ни было предсталений о программировании вообще.
он навязан мелкомягкими для воплощения своих планов по захвату мира.
Правда язык появился раньше, чем Майкрософт, но в Вашей кратине мира, как я понимаю, это неважно.
если по моему вопросу вы знаете, как чтото сделать - то пишите
И что я с этого буду иметь? Я Вам попытался писать про то, что работа с float здесь неоправдана, но Вы не слушаете, т.к. знаетё больше и лучше меня. Если бы Вы задали вопрос, "а как без неё обойтись", я бы ответил, но Вы начали нести какой-то бред про строки ... Вам виднее.
вообще ничего не пишите ...
свои умозаключения на эту тему держать при себе ...
С Вашего позволения (или, даже, без оного) я сам решаю и буду решать что мне писать, а что не писать.
умнее в глазах других будете выглядеть.
Мне абсолютно пофигу как я выгляжу в Ваших глазах.
Сам ты масдай! На этом языке Линух написан!
Тогда, в начале Сишных времён, никаких мелкомягких не было.
А мелкомяхкие сделали свой ублюдочный Quick C в 1990 или 1992-м году.
если бы не мелкомягкие - то Си и его вариации так бы и остались на уровне малоизвестных и неиспользуемых почти нигде и никак недоязыков.
И сразу "памагите!!!" - хоть бы пару месяцев позанимался.
....
Характер вопросов, которые Вы задаёте говорит не о незнении языкка, а об отстутствии каких бы то ни было предсталений о программировании вообще.
я не програмист, хотя и знаю несколько языков на уровне выше университетского, но в их перечень С не входит.
И что я с этого буду иметь?
это не комерческий форум - если вы хотите свои знания продавать - то вы ошиблись местом....
Я Вам попытался писать про то, что работа с float здесь неоправдана,. Если бы Вы задали вопрос, "а как без неё обойтись", я бы ответил, но Вы начали нести какой-то бред про строки ...
я, вроде как, не двусмыслено спросил чем её заменить, тк вроме строк я не предствляю пока чем её заменить
если бы не мелкомягкие - то Си и его вариации так бы и остались на уровне малоизвестных и неиспользуемых почти нигде и никак недоязыков.
ELITE, ты в курсе чего эта баба так улыбается?
Знаешь, такого Высоцкого В.С.? Так вот он эту загадку разгадал:
«Все ухмылялась Джоконда: Мол, дурачок, дурачок!»
знаю несколько языков на уровне выше университетского
Это заметно.
это не комерческий форум - если вы хотите свои знания продавать
А я где-то что говорил про коммерцию и про продажу? У Вас богатая фантазия, только мне её не приписывайте.
они же раскрутили его как язык (все его вариации) и подражатели на лине тудаже пошли
если бы не мелкомягкие - то Си и его вариации так бы и остались на уровне малоизвестных и неиспользуемых почти нигде и никак недоязыков.
Дак опять враки. Вы были сами этому свидетелем? А я был. Тогда, в 90-е очень популярен был Borland и Zortech С++. Микрософтовскую убогую поделку никто и за язык не считал, там и раскручивать нечего было. Она и подохла благополучно вместе с DOS. Borland пропурхался гораздо дольше. И нынешний Visual Studio C++ это не эволюция Quick C, а продукт сторонних разработчиков, которых мелкомяхкие скупили вместе с гагном. Популярность С идёт из Unix.
Читать не надо прекращать, даже после универа. И совсем не Википедию.
Характер вопросов, которые Вы задаёте говорит не о незнении языкка, а об отстутствии каких бы то ни было предсталений о программировании вообще.
я не програмист, хотя и знаю несколько языков на уровне выше университетского, но в их перечень С не входит.
Никто не подвергает сомнению Ваши филологические способности, здесь лишь констатируют, что Вы не имеете представление о том, что такое программирование.
я не програмист, хотя и знаю несколько языков на уровне выше университетского, но в их перечень С не входит.
Евгений точно поймет, остальные, вроде, помоложе будут...
- Какое у Вас образование?
- Университетское!
- А какой, простите, университет?
- Ленинский унивеситет миллионов!
(Для юных поясню: в гребаном совке, в мою юность, была передача по телевизору, каналов тогда было 4 - 1ый, 2ой, местный (на 3-ем, в Москве - московский) и учебный, на 4-ом). Передача - агитмусор с пропагандой социализьмуса.
Ну зря вы так про Ленинский университет миллионов. Он же там не программированию,и не языку Си учил. Да и ящик это был тогдашний интернет - такая же помойка.
и учебный, на 4-ом)
Это тот, где сеньор Панталоне расхаживал? Он, вроде, Си не обучал. Хотя, может, это как раз Си и был - в 10 утра, обычно, никого уж у телевизора и не было кроме бабушек и больных. Остальные лес валили в закрома родины.
ладно погарячился малость, забудем обиды и встретим новый год :) 3 дня осталось.
//по образованию я информатик-аналитик
программирование в этот курс входит необходимое для понимания курса, но уровень минимальный и на 2х десятках языках - в общем по сути вводный курс
программы пишу простенькие и редко - поэтому в основном говнокод выходит, хотя и стремлюсь к оптимизации
самое большое что я писал - вот https://cloud.mail.ru/public/14yz/pKKH6xFCR
это на Jass+(сJass и vJass немного) код одной из написанных мной игр, которая уже 7 лет живет и всё еще имеет небольшую популярность
в 90е начинал немнго с бейсика, потом паскаль и дельфи - но всё по минимому...
делал сайты не сложные (php+js+mysql)
а по теме - я немного переписал (дописал) библиотеку LedControl.h - а именно добавил возможность отправлять байты на прямую
и изменил код, чтобы работать с таблицей сопоставления и где надо - довносить на прямую изменения в нужный символа |=Bxxxxxxxx
//кстати на http://arduino.on.kg справичник побогаче оказался
//кстати на http://arduino.on.kg справичник побогаче оказался
Откройте для себя первоисточник уж коли вы "знаток языков с универститетским образованием" :)
.
.
-.
Привет всем!
На основании этой ветки форума, у меня получилось вывести любое число (от 0 до 9999) на дисплейчик TM1637.
В этом учебном коде выводятся все числа, начиная с 't_start' и заканчивая 't_max' на экран 4х символьного дисплейчика.
#include "TM1637.h" #define CLK 3 #define DIO 2 TM1637 tm1637(CLK,DIO); unsigned char c[4]; unsigned int t_start = 0; unsigned int t_max = 9999; unsigned int t = t_start; unsigned int tmp; void setup() { tm1637.init(); tm1637.set(BRIGHT_TYPICAL); } void loop() { if (t == t_max) t = t_start; tmp = t; for (int i=0; i <4; i++) { c[i] = (t % 10); t /=10; } tm1637.display(0, c[3]); tm1637.display(1, c[2]); tm1637.display(2, c[1]); tm1637.display(3, c[0]); delay(50); t = tmp; t ++; }Буду рад, если кому пригодиться :)
Invisible
вот только вывод из строк 27-30 можно переместитже в цикл 22-25
и делей убрать ! - вызывать таймером
Ой, мамочки! Спец. по двадцати языкам вернулся, чтобы нас убогих поучить! А мы уж и скучать начали :)
Хорошо, что иногда они возвращаются!
Кстати, я что-то не заметил, что Invisible просил(а) комментировать его(её) код, так чего лезешь?
ой тебя забыл спросить.... спец ты наш....
моя тема - хочу отвечаю, хочу не отвечаю....
ой тебя забыл спросить....
Маладец, что призаёшь свои ошибки! Впредь не забывай!
моя тема - хочу отвечаю, хочу не отвечаю....
Логично! )))
Спасибо за полезные советы! Только подскажите пожалуйста, что означает "вызывать таймером" ???
Я только учусь разбираться с ардуинкой. Приведите пример, как "вызывать таймером" ?
Invisible
значит ставить в код таймер (на millis() ) на нужное время и по его срабатыванию выполнять нужный код
а не использовать делей - он "вешает" фактически МК, поэтому ничего иного в это время МК делать не может
Спасибо за полезные советы! Только подскажите пожалуйста
Вообще-то по Вашему коду до хрена чего можно подсказать, просто, как тут было правильно отмечено, Вы об этом не просили.
Спасибо )