Помогите реализовать запись числа с точкой
-
Andrey19888
- Родился
- Сообщения: 12
- Зарегистрирован: Вс июл 16, 2006 23:52:49
Помогите реализовать запись числа с точкой
С Ик пульта вводится число с плавающей точкой. Т.е. для получения числа, например, 0.005 вводится сначала 0, затем точка, затем еще 2 нуля и 5. Посоветуйте как грамотно организовать запись данных в переменную Float
Пишу на СИ CVAVR
Пишу на СИ CVAVR
Жизнь как рояль: клавиша белая, клавиша черная, крышка
-
codenamehawk
- Вымогатель припоя
- Сообщения: 528
- Зарегистрирован: Вт фев 09, 2010 17:52:26
Re: Помогите реализовать запись числа с точкой
В библиотеке stdlib.h
есть функция
float atof(char *str)
converts the characters from string str to floating point.
должна вам помочь.
есть функция
float atof(char *str)
converts the characters from string str to floating point.
должна вам помочь.
-
Andrey19888
- Родился
- Сообщения: 12
- Зарегистрирован: Вс июл 16, 2006 23:52:49
Re: Помогите реализовать запись числа с точкой
Спасибо огромное. Попробую. О результате отпишусь 
Жизнь как рояль: клавиша белая, клавиша черная, крышка
-
Andrey19888
- Родился
- Сообщения: 12
- Зарегистрирован: Вс июл 16, 2006 23:52:49
Re: Помогите реализовать запись числа с точкой
Сделал по совету и столкнулся с проблемой
unsigned char *add = "12.075";
char s[20];
sdf=atof(add);
sprintf(s,"%f",sdf);
lcd_puts(s);
в итоге на экране имеем вместо 12.075 12.074999
unsigned char *add = "12.075";
char s[20];
sdf=atof(add);
sprintf(s,"%f",sdf);
lcd_puts(s);
в итоге на экране имеем вместо 12.075 12.074999

Жизнь как рояль: клавиша белая, клавиша черная, крышка
Re: Помогите реализовать запись числа с точкой
sprintf(s,"%.3f",sdf);
-
Andrey19888
- Родился
- Сообщения: 12
- Зарегистрирован: Вс июл 16, 2006 23:52:49
Re: Помогите реализовать запись числа с точкой
Спасибо. Заработало. Единственный момент, что в переменной sdf по прежнему остается неточное значение, а мне с ней нужно будет работать. Как там можно поправить?
Жизнь как рояль: клавиша белая, клавиша черная, крышка
-
codenamehawk
- Вымогатель припоя
- Сообщения: 528
- Зарегистрирован: Вт фев 09, 2010 17:52:26
Re: Помогите реализовать запись числа с точкой
Andrey19888 писал(а):Сделал по совету и столкнулся с проблемой
unsigned char *add = "12.075";
char s[20];
sdf=atof(add);
sprintf(s,"%f",sdf);
lcd_puts(s);
в итоге на экране имеем вместо 12.075 12.074999
Попробуйте так
Код: Выделить всё
unsigned char add[7] = "12.075";
unsigned char s[20];
float sdf;Код: Выделить всё
sdf=atof(add);
sprintf(s,"%f",sdf);
-
Andrey19888
- Родился
- Сообщения: 12
- Зарегистрирован: Вс июл 16, 2006 23:52:49
Re: Помогите реализовать запись числа с точкой
Безрезультатно. На экране всеравно 12,074999. Если в sprintf(s,"%.3f",sdf); на экране правильно, но в переменной же всеравно нет 
Жизнь как рояль: клавиша белая, клавиша черная, крышка
Re: Помогите реализовать запись числа с точкой
Поставь вместо типа данных float double.
-
Andrey19888
- Родился
- Сообщения: 12
- Зарегистрирован: Вс июл 16, 2006 23:52:49
Re: Помогите реализовать запись числа с точкой
Ставил .. не помогает. Я уже неделю борюсь с этой проблемой 
Жизнь как рояль: клавиша белая, клавиша черная, крышка
-
codenamehawk
- Вымогатель припоя
- Сообщения: 528
- Зарегистрирован: Вт фев 09, 2010 17:52:26
Re: Помогите реализовать запись числа с точкой
Andrey19888 писал(а):Безрезультатно. На экране всеравно 12,074999. Если в sprintf(s,"%.3f",sdf); на экране правильно, но в переменной же всеравно нет
Это похоже функция sprintf выдает такой результат, а переменная sdf равна 12.075
-
codenamehawk
- Вымогатель припоя
- Сообщения: 528
- Зарегистрирован: Вт фев 09, 2010 17:52:26
Re: Помогите реализовать запись числа с точкой
Вывод на экран sprintf(s,"%8.3f",sdf);
Где 8 общее количевство знаков в (s), а 3 количевство знаков после запятой.
Где 8 общее количевство знаков в (s), а 3 количевство знаков после запятой.
Последний раз редактировалось codenamehawk Ср янв 05, 2011 12:59:33, всего редактировалось 1 раз.
-
Andrey19888
- Родился
- Сообщения: 12
- Зарегистрирован: Вс июл 16, 2006 23:52:49
Re: Помогите реализовать запись числа с точкой
Сейчас проведу эксперимент попробую сравнить sdf c числом 12.075.
Вот тут народ тоже пишет про такие проблемы
http://www.avrfreaks.net/index.php?name ... 49&start=0
Вот тут народ тоже пишет про такие проблемы
http://www.avrfreaks.net/index.php?name ... 49&start=0
Жизнь как рояль: клавиша белая, клавиша черная, крышка
-
codenamehawk
- Вымогатель припоя
- Сообщения: 528
- Зарегистрирован: Вт фев 09, 2010 17:52:26
Re: Помогите реализовать запись числа с точкой
Посмотрите пример
Не забывайте, что если для float попробуете задать число типа 12.0000000075 , оно будет округленно.
Почитайте http://ru.wikipedia.org/wiki/%D0%A7%D0% ... 0%BE%D0%B9
Не забывайте, что если для float попробуете задать число типа 12.0000000075 , оно будет округленно.
Почитайте http://ru.wikipedia.org/wiki/%D0%A7%D0% ... 0%BE%D0%B9
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Помогите реализовать запись числа с точкой
опять перепетии с float... ну не нужно его применять! поверьте, можно обойтись и без него, а значит, и не иметь всех проблем, с ним связанных: большого объема кода, проблемы округления, медленной скорости расчетов...
вы передаете ряд цифр, среди которых есть точка, положение точки по сути своей определяет множитель (или делитель, что непринципиально), на который надо умножить(разделить) число.
передаете 12.345 - это значит, число 12345 гнадо разделить на 1000
передаете 12.3 - это знсчит, число 123 надо разделить на 10
и т.д.
для хранения числа выбирайте, предположим, long - думаю, вам хватит с запасом на все случаи жизни. итак, принимаете цифры числа, запоминаете число в переменной long, а положение точки задает вам другое число - делитель, для котрого хватит и обычного int, хотя и long можно не пожалеть.
далее корректируете свою математику в программе так, чтобы ВСЕ расчеты велись в принятом формате: отдельно числа, отдельно делители - это просто! вычисляете все действия над числами, результат преобразуете в строку и вставляете в эту строку в нужное место точку: место этой точки определяется элементарными действиями над ДЕЛИТЕЛЯМИ - это тоже несложно, не так ли?
в итоге вы имеете очень компактный и простой код, работающий быстро. все это называется "математика с фиксированной точкой", в которой все действия осуществляются НАД ЦЕЛЫМИ ЧИСЛАМИ. в некоторых случаях можно еще сильнее упростить задачу, если подумать получше...
вы передаете ряд цифр, среди которых есть точка, положение точки по сути своей определяет множитель (или делитель, что непринципиально), на который надо умножить(разделить) число.
передаете 12.345 - это значит, число 12345 гнадо разделить на 1000
передаете 12.3 - это знсчит, число 123 надо разделить на 10
и т.д.
для хранения числа выбирайте, предположим, long - думаю, вам хватит с запасом на все случаи жизни. итак, принимаете цифры числа, запоминаете число в переменной long, а положение точки задает вам другое число - делитель, для котрого хватит и обычного int, хотя и long можно не пожалеть.
далее корректируете свою математику в программе так, чтобы ВСЕ расчеты велись в принятом формате: отдельно числа, отдельно делители - это просто! вычисляете все действия над числами, результат преобразуете в строку и вставляете в эту строку в нужное место точку: место этой точки определяется элементарными действиями над ДЕЛИТЕЛЯМИ - это тоже несложно, не так ли?
в итоге вы имеете очень компактный и простой код, работающий быстро. все это называется "математика с фиксированной точкой", в которой все действия осуществляются НАД ЦЕЛЫМИ ЧИСЛАМИ. в некоторых случаях можно еще сильнее упростить задачу, если подумать получше...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
codenamehawk
- Вымогатель припоя
- Сообщения: 528
- Зарегистрирован: Вт фев 09, 2010 17:52:26
Re: Помогите реализовать запись числа с точкой
Если у вас в предложении
заменить на "при определенных условиях, не стоит применять float", то я ваш совет поддержу.
Но если проц быстрый и места много, почему бы float не применить ?
Трудности при изучении, возникают как правило всегда,
но это не повод отказаться от того, что не получается написать с наскоку.
ARV писал(а):опять перепетии с float... ну не нужно его применять!
заменить на "при определенных условиях, не стоит применять float", то я ваш совет поддержу.
Но если проц быстрый и места много, почему бы float не применить ?
Трудности при изучении, возникают как правило всегда,
но это не повод отказаться от того, что не получается написать с наскоку.
-
clawham
- Поставщик валерьянки для Кота
- Сообщения: 1957
- Зарегистрирован: Пт окт 31, 2008 09:38:55
- Откуда: Одесса
- Контактная информация:
Re: Помогите реализовать запись числа с точкой
ARV, разрешите тогда Вас ещё одним примером нагрузить...
Делаю миксер для вертолёта - суть в том что входные сигналы - это импульс длительностью от 1000 us до 2000 us (1-2 милисеки) повторяются они 20 рас в секунду...таких каналов в передатчике 6 как и в приёмнике....мне надо сделать так чтоб контроллер захватил один сигнал(общий газ) и потом вывел результат в аппаратный ШИМ (управление двигателями) но...если второй входной сигнал = 1520 нс - то оба канала копируются-тоесть:
вход 1=1000 - на выход 0 0
вход 1=1500 - на выход 256 256
вход 1=2000 - на выход 511 511
теперь второй вход это дизбаланс - если на втором входе меньше 1520 то первый выход уменьшается пропорционально отклонению от нейтрали а второй - увеличивается и наоборот
тоесть так:
вход 1 всегда 1500(для примера)
вход 2=1520 - выходы 256 256
вход 2=1600 - выходы 266 246
вход 2=1400 - выходы 246 266
вот так примерно....но ещё есть другая вещь- степень влияния тоесть когда второй сигнал в нуле то при среднем значении первого канала первый выход равен 0 а второй - максимуму
а бывает надо "затупить" это дело...тоесть уменьшить диапазон влияния в 2 раза в 3 или в 1.78 например(задавать с третего канала
ТАК ВОТ....сейчас я это делаю так:
суть работы - таймер считает микросекунды и в переменных In_Gyro и Gas_in появляются значения длительности импульса в микросекундах...
здесь я затупил влияние разбалансового второгосигнала(гироскопа) в два раза...а хочется взять третий канал и с пульта на лету это дело корректировать...а ещё внести Экспоненту но это потом....
так вот....как бы это всё можно было б упростить....получается малая дискретность того флоата что расчитывается в строке
ведь мы приводим его к диапазону 0...1 а потом умножаем на нужный мне выходной диапазон(для PWM регистра)
при этом значения минимума, максимума и среднего положения длительности сигнала калибруется/меняется/расчитывается при включении(например разбалансный центр может быть не 1520 как опложено а 1401, а минимум не 1000 а 983, а максимум не 2000 а 1973)
Делаю миксер для вертолёта - суть в том что входные сигналы - это импульс длительностью от 1000 us до 2000 us (1-2 милисеки) повторяются они 20 рас в секунду...таких каналов в передатчике 6 как и в приёмнике....мне надо сделать так чтоб контроллер захватил один сигнал(общий газ) и потом вывел результат в аппаратный ШИМ (управление двигателями) но...если второй входной сигнал = 1520 нс - то оба канала копируются-тоесть:
вход 1=1000 - на выход 0 0
вход 1=1500 - на выход 256 256
вход 1=2000 - на выход 511 511
теперь второй вход это дизбаланс - если на втором входе меньше 1520 то первый выход уменьшается пропорционально отклонению от нейтрали а второй - увеличивается и наоборот
тоесть так:
вход 1 всегда 1500(для примера)
вход 2=1520 - выходы 256 256
вход 2=1600 - выходы 266 246
вход 2=1400 - выходы 246 266
вот так примерно....но ещё есть другая вещь- степень влияния тоесть когда второй сигнал в нуле то при среднем значении первого канала первый выход равен 0 а второй - максимуму
а бывает надо "затупить" это дело...тоесть уменьшить диапазон влияния в 2 раза в 3 или в 1.78 например(задавать с третего канала
ТАК ВОТ....сейчас я это делаю так:
Код: Выделить всё
unsigned int Mem_Min_Gas = 1000;
unsigned int Mem_Max_Gas = 2000;
unsigned int Mem_Min_Gyro = 1000;
unsigned int Mem_Max_Gyro = 2000;
float TempA = 0;
float TempB = 0;
float Delta_Gas = 0;
float Delta_Gyro = 0;
//ждём пока вход Газ упадёт в нуль
while(Gas_in);
//теперь ждём поднятия в 1
//TCCR2=TimOn;
TCCR2=0x00; // таймер глушим
Timer_ext = 0; // обнуляем накопитель таймера
TCNT2 = 0;
#asm("wdr") // обнулили и сам таймер
while(!Gas_in);
//запускаем таймер
TCCR2=TimOn;
// ждём пока вход Газ упадёт вниз
while(Gas_in);
//срочно тормозим таймер
TCCR2=0x00;
// расчитываем кол-во отсчетов от нуля
In_Gas = TCNT2+Timer_ext;
#asm("wdr")
//ждём пока вход Гиры упадёт в нуль
while(Gyro_in);
//теперь ждём поднятия в 1
//TCCR2=TimOn;
TCCR2=0x00; // таймер глушим
Timer_ext = 0; // обнуляем накопитель таймера
TCNT2 = 0; // обнулили и сам таймер
while(!Gyro_in);
//запускаем таймер
TCCR2=TimOn;
// ждём пока вход Гyro упадёт вниз
while(Gyro_in);
//срочно тормозим таймер
TCCR2=0x00;
// расчитываем кол-во отсчетов от нуля
In_Gyro = TCNT2+Timer_ext;
// расчитываем выход газа
//TempA = (float)(Gas_in-Mem_Min_Gas)/(Mem_Max_Gas-Mem_Min_Gas)*0x03ff;
TempA = (float)(In_Gas);
TempA = TempA - (float)(Mem_Min_Gas);
Delta_Gas = Mem_Max_Gas;
Delta_Gas-= Mem_Min_Gas;
TempA = TempA/Delta_Gas;
TempA = TempA * 500.0;
// расчитываем выход гиры
//TempA = (float)(Gas_in-Mem_Min_Gas)/(Mem_Max_Gas-Mem_Min_Gas)*0x03ff;
TempB = (float)(In_Gyro);
TempB = TempB - (float)(Mem_Min_Gyro);
Delta_Gyro = Mem_Max_Gyro;
Delta_Gyro-= Mem_Min_Gyro;
TempB = TempB/Delta_Gyro;
TempB = TempB * 500.0;
Delta_Gyro = (TempB-Gyro_Centr)/2;
TempB = TempA;
TempA = TempB+Delta_Gyro;
TempB = TempB-Delta_Gyro;
if(TempA<0)
TempA = 0;
if(TempA>510)
TempA = 510;
if(TempB<0)
TempB = 0;
if(TempB>510)
TempB = 510;
OCR1A = TempA;
OCR1B = TempB;
суть работы - таймер считает микросекунды и в переменных In_Gyro и Gas_in появляются значения длительности импульса в микросекундах...
здесь я затупил влияние разбалансового второгосигнала(гироскопа) в два раза...а хочется взять третий канал и с пульта на лету это дело корректировать...а ещё внести Экспоненту но это потом....
так вот....как бы это всё можно было б упростить....получается малая дискретность того флоата что расчитывается в строке
Код: Выделить всё
TempA = TempA/Delta_Gas;
TempA = TempA * 500.0;
ведь мы приводим его к диапазону 0...1 а потом умножаем на нужный мне выходной диапазон(для PWM регистра)
при этом значения минимума, максимума и среднего положения длительности сигнала калибруется/меняется/расчитывается при включении(например разбалансный центр может быть не 1520 как опложено а 1401, а минимум не 1000 а 983, а максимум не 2000 а 1973)
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
Не доверяйте русским лужам - это может быть вход в метро.
-
Andrey19888
- Родился
- Сообщения: 12
- Зарегистрирован: Вс июл 16, 2006 23:52:49
Re: Помогите реализовать запись числа с точкой
codenamehawk писал(а):Andrey19888 писал(а):Безрезультатно. На экране всеравно 12,074999. Если в sprintf(s,"%.3f",sdf); на экране правильно, но в переменной же всеравно нет
Это похоже функция sprintf выдает такой результат, а переменная sdf равна 12.075
Как не парадоксально, но вот что я сделал
float sdf=0.0;
unsigned char *add = "12.075";
sdf=atof(add);
if (sdf==12.075){
lcd_putsf("ok");
};
И на дисплей вывелось ОК ...т.е. получается что ф-я sprintf не корректно отрабатывает.
ARV у меня уже были попытки реализации по вашему алгоритму, но у меня вводится может как оч маленькое число 0.005 например так и 135.26. И тогда представлять становится довольно сложно, темболее ввод идет по 1 цифре с пульта
Жизнь как рояль: клавиша белая, клавиша черная, крышка
-
codenamehawk
- Вымогатель припоя
- Сообщения: 528
- Зарегистрирован: Вт фев 09, 2010 17:52:26
Re: Помогите реализовать запись числа с точкой
Примените sprintf(s,"%8.3f",sdf); 
-
Andrey19888
- Родился
- Сообщения: 12
- Зарегистрирован: Вс июл 16, 2006 23:52:49
Re: Помогите реализовать запись числа с точкой
С выводом я уже разобрался. Волновала только проблема что в переменной хранится не правильное число. Но эксперимент показал что функция sprintf не корректно отрабатывает и приходится округлять
Жизнь как рояль: клавиша белая, клавиша черная, крышка