Форум русскоязычного сообщества Ubuntu


Автор Тема: strtof / strtod и десятичная точка  (Прочитано 2726 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Белый пони

  • Автор темы
  • Любитель
  • *
  • Сообщений: 63
    • Просмотр профиля
strtof / strtod и десятичная точка
« : 29 Июня 2010, 11:36:08 »
Столкнулся с тем, что в Qt Creator'е strtof не воспринимает точку в качестве разделителя дробной и целой части.
В консольном приложении всё окей. Вот, например, кусок консольной проги получающей частоту процессора из текста dmesg:

...
FILE *CPUpar;
char tempstring[255];
float frequency = 0;

CPUpar = fopen( "CPU_inf1.txt", "r");

while(1)
{
fgets ( tempstring, 200, CPUpar);
if (strstr( tempstring, "MHz processor") != NULL)
{
printf( "%s", tempstring );

frequency = strtof( tempstring + 23 , NULL);

printf("\n CPU speed: %f MHz", frequency );
}

if (strstr( tempstring, "pikachu") != NULL)   //это метка конца файла
{
printf("......finished.\n");
break;
}
}
...

Результат:
[    0.000000] Detected 3014.452 MHz processor.

 CPU speed: 3014.451904 MHz......finished.

(откуда погрешность берётся я тоже не понял :( )

Когда делаю то же самое в проекте в Creator'е, strtof останавливается перед точкой и частота получается 3014,000000.

Можно это как-то подправить?

(пока считываю в два захода, сначала целую часть,  потом прибавляю дробную(делёную на 1000) )    


« Последнее редактирование: 29 Июня 2010, 13:31:38 от Белый пони »

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: strtof / strtod в Qt
« Ответ #1 : 29 Июня 2010, 12:41:35 »
К Qt вопрос отношения не имеет лучше подправить тему.
Цитировать
if (strstr( tempstring, "pikachu") != NULL)   //это метка конца файла
Интересный новый подход :) но мне как-то старый вариант через корректную проверку на конец файла, например через проверку того, что возвращает fgets больше нравиться:
Цитировать
char* fgets(char* s, int n, FILE* stream);
Copies characters from (input) stream stream to s, stopping when n-1 characters copied, newline copied, end-of-file reached or error occurs. If no error, s is NUL-terminated. Returns NULL on end-of-file or error, s otherwise.

Если про ручной сборке и сборке в QtCreator программа работает по разному, то приведи как собиарл руками и какие команды запкскал QtCreator (у него есть вкладка где реальные команды компилятора показаны). Без этого разобраться и подсказать что-то затруднительно.
« Последнее редактирование: 29 Июня 2010, 12:46:12 от VestniK »

Оффлайн Белый пони

  • Автор темы
  • Любитель
  • *
  • Сообщений: 63
    • Просмотр профиля
Re: strtof / strtod в Qt
« Ответ #2 : 29 Июня 2010, 13:30:58 »
К Qt вопрос отношения не имеет лучше подправить тему.
char* fgets(char* s, int n, FILE* stream);
Copies characters from (input) stream stream to s, stopping when n-1 characters copied, newline copied, end-of-file reached or error occurs. If no error, s is NUL-terminated. Returns NULL on end-of-file or error, s otherwise.
Точно. Поправлю :)

Цитировать
Если про ручной сборке и сборке в QtCreator программа работает по разному, то приведи как собиарл руками и какие команды запкскал QtCreator (у него есть вкладка где реальные команды компилятора показаны). Без этого разобраться и подсказать что-то затруднительно.


 Ну не совем "сбоирал руками", просто консольное приложение скомпилировал:
g++ -o cpu6 get_cpuMHz.cpp
 Если я правильно понял, реальные команды Creator'а в закладке Build Settings -> Build Steps

1) Gdb Marcos Build
2) QMake, аргументы:
/qtest/ske8_1/ske8_1.pro -spec /usr/share/qt4/mkspecs/linux-g++ -r CONFIG+=debug_and_release CONFIG+=debug3) Make, аргументы:
debug

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: strtof / strtod и десятичная точка
« Ответ #3 : 29 Июня 2010, 13:50:06 »
Нет, ты когда сборку делаешь, там в одной из вкладок внизу есть возможность непосредственно посмотреть какие команды были запущены.

Оффлайн Белый пони

  • Автор темы
  • Любитель
  • *
  • Сообщений: 63
    • Просмотр профиля
Re: strtof / strtod и десятичная точка
« Ответ #4 : 29 Июня 2010, 14:58:27 »
Нет, ты когда сборку делаешь, там в одной из вкладок внизу есть возможность непосредственно посмотреть какие команды были запущены.
Это?
Compile output:
Running build steps for project ske8_1...
Creating gdb macros library...
Starting: /usr/bin/qmake-qt4 /qtest/ske8_1/ske8_1.pro -spec /usr/share/qt4/mkspecs/linux-g++ -r CONFIG+=debug_and_release CONFIG+=debug
Exited with code 0.
Starting: /usr/bin/make debug -w
make: Entering directory `/qtest/ske8_1'
/usr/bin/make -f Makefile.Debug
make[1]: Entering directory `/qtest/ske8_1'
/usr/bin/uic-qt4 mainwidget.ui -o ui_mainwidget.h
g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Idebug -I. -o debug/main.o main.cpp
g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Idebug -I. -o debug/mainwidget.o mainwidget.cpp
g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Idebug -I. -o debug/read8thread.o read8thread.cpp
g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Idebug -I. -o debug/buffthread.o buffthread.cpp
/usr/bin/moc-qt4 -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Idebug -I. mainwidget.h -o debug/moc_mainwidget.cpp
g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Idebug -I. -o debug/moc_mainwidget.o debug/moc_mainwidget.cpp
/usr/bin/moc-qt4 -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Idebug -I. read8thread.h -o debug/moc_read8thread.cpp
g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Idebug -I. -o debug/moc_read8thread.o debug/moc_read8thread.cpp
g++  -o ske8_1 debug/main.o debug/mainwidget.o debug/read8thread.o debug/buffthread.o debug/moc_mainwidget.o debug/moc_read8thread.o    -L/usr/lib -lQtGui -lQtCore -lpthread
make[1]: Leaving directory `/qtest/ske8_1'
make: Leaving directory `/qtest/ske8_1'
Exited with code 0.

Оффлайн Sova777

  • Участник
  • *
  • Сообщений: 208
    • Просмотр профиля
    • Несколько слов о NetBeans C/C++ Pack'е
Re: strtof / strtod и десятичная точка
« Ответ #5 : 29 Июня 2010, 16:06:09 »
Что возвращает этот код:
struct lconv * lc;
lc=localeconv();
cout << "decimal_point: " << lc->decimal_point << endl;
Пользователь OpenSolaris 2008.11, Ubuntu 8.10, Windows XP. Mac OS X не нравится, стараюсь не использовать.

Оффлайн Белый пони

  • Автор темы
  • Любитель
  • *
  • Сообщений: 63
    • Просмотр профиля
Re: strtof / strtod и десятичная точка
« Ответ #6 : 30 Июня 2010, 10:05:16 »
Что возвращает этот код:
struct lconv * lc;
lc=localeconv();
cout << "decimal_point: " << lc->decimal_point << endl;

В консольном приложении - точка, в Creator'е - запятая. Намёк понял:)
Cпасибо!:)

Попробовал перед strtof :setlocale( LC_NUMERIC, "C");  - заработало, это нормальное решение? Рекомендуется ли после чтения числа вернуть  обратно настройки локали ( setlocale( LC_ALL, ""); ) ?


И ещё вопрос, а как погрешность убрать? А то из строки "3014.200" получается число 3014.199951, например. Перед считыванием переменная равна нулю ( 0.000000 ).

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: strtof / strtod и десятичная точка
« Ответ #7 : 30 Июня 2010, 11:44:05 »
Наверно проще всего убрать погрешность не конвертируя строку в число. Числа с плавающей точкой на самом деле не произвольное действительное число погут представить, а только ограниченное подмножество оных. Или тебе принципиально с ним именно как с числом работать?

Оффлайн Белый пони

  • Автор темы
  • Любитель
  • *
  • Сообщений: 63
    • Просмотр профиля
Re: strtof / strtod и десятичная точка
« Ответ #8 : 30 Июня 2010, 14:10:01 »
Наверно проще всего убрать погрешность не конвертируя строку в число. Числа с плавающей точкой на самом деле не произвольное действительное число погут представить, а только ограниченное подмножество оных. Или тебе принципиально с ним именно как с числом работать?
Принципиально. Я потом использую эту частоту, чтобы измерять маленькие интервалы времени с помощью rdtsc().

Да, похоже, число 3014.200 просто не входит в список значений float. Сделал обычную float константу с таким значением,  в результате printf показал всё те же 3014.199951 .
 
Как вариант вместо float сделал переменную double, получилось 3014.199999999999818101 , точно до 12-го знака после запятой, т.е. всего 16 значащих цифр, вроде как это максимум для double, дальшя я, наверно, уже вышел за область памяти переменной.   Такой точности в рассчётах хватит, я думаю :)  (хотя если в dmesg выдаётся только три знака после, то делать переменную точнее float смысла нет)

PS тут ещё подумалось, может есть способ получить частоту с большей точностью, чем в dmesg?
« Последнее редактирование: 30 Июня 2010, 14:25:39 от Белый пони »

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: strtof / strtod и десятичная точка
« Ответ #9 : 30 Июня 2010, 14:25:08 »
Если удасться организовать такой способ измерения времени попробуй измерить погрешность и написать тут. Любопытно узнать какая ошибка при этом набегает за секунду.

Оффлайн Белый пони

  • Автор темы
  • Любитель
  • *
  • Сообщений: 63
    • Просмотр профиля
Re: strtof / strtod и десятичная точка
« Ответ #10 : 30 Июня 2010, 14:49:57 »
Если удасться организовать такой способ измерения времени попробуй измерить погрешность и написать тут. Любопытно узнать какая ошибка при этом набегает за секунду.

Вот кусок кода, который измеряет паузу
ini = rdtsc();
end = rdtsc();Ini = ini;
printf("\n rdtsc itself : %llu ticks,\t %fµs\n", end - ini, time);

ini = rdtsc();
usleep(0);
end = rdtsc();
time = (end -ini) / MHz;
printf("usleep itself : %llu ticks,\t %fµs\n\n", end - ini, time);

ini = rdtsc();
usleep(1000);
end = rdtsc();
time = (end -ini) / MHz;
printf("   1ms__tick count: %llu\t actual sleep = %.2fµs\n", end - ini, time);

функция rdtsc():
extern __inline__ uint64_t rdtsc() {
   uint64_t x;
   __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
   return x;
 }
(подсмотрено тут - http://www.iakovlev.org/index.html?p=536)

В одном случае константа MHz=3014.200 типа float, в другом - double.

(Нажмите, чтобы показать/скрыть)

(Нажмите, чтобы показать/скрыть)

Вообщем, с учётом погрешности скорости выполнения самого rdtsc() и usleep() разницы не видно.

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: strtof / strtod и десятичная точка
« Ответ #11 : 30 Июня 2010, 15:14:55 »
Да хорошая точность. Спасибо за результаты измерений.

 

Страница сгенерирована за 0.034 секунд. Запросов: 25.