C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Работа с float
Евгений
Отправлено: 14.03.2005, 18:57


Не зарегистрирован







У меня сразу два вопроса.

Первый: какой стандартной функцией можно окрулить (обрезать — если есть) данные типа float. Получаю к примеру: 1,68451265 и т.д., а хочу получить округление до требуемого знака ?

Второй вопрос:
В Windows есть настройка региональных стандартов, где в качестве разделителя целой и дробной части можно выбрать или символ запятой или символ точки. Соответственно у каждого конечного пользователя эти настройки разные. А вопрос такой: каким образом это учесть в работе прогрммы, если я при помощи функции StrToFloat перевожу строку в число с плавающей точкой, но строка (которая должна стать float) может содержать как точку, так и запятую. Соответственно возникает или не возникает ошибка при 'переводе' из одного типа в другой. Вот как это учитывать ?
Ящер
Отправлено: 14.03.2005, 21:05


Ученик-кочегар

Группа: Участник
Сообщений: 11



Я написал простенькую функция по обработке строки которая меняла все запятые в строке на точке или наоборот.... Выкрутился так..

а по округлению. Даже не знаю что посоветоват.. Смотря где тебе это надо.... можешь сам математически округлять, но это не очень красиво. Если надо получить формат при преобразовании в строку то смотри FloatToStrF()
xim
Отправлено: 14.03.2005, 22:56


Станционный диспетчер

Группа: Участник
Сообщений: 143



QUOTE
В Windows есть настройка региональных стандартов, где в качестве разделителя целой и дробной части можно выбрать или символ запятой или символ точки. Соответственно у каждого конечного пользователя эти настройки разные.

CODE
DecimalSeparator=char(<тот, который нужен>);

AVC
Отправлено: 15.03.2005, 09:21


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE
В Windows есть настройка региональных стандартов, где в качестве разделителя ...


Можно повториться?
Включаете в Main следующий код
CODE

Application->UpdateFormatSettings = false;
DecimalSeparator = '.';
ListSeparator = ',';
DateSeparator = '.';
ShortDateFormat = "dd.mm.yyyy";

и после этого приложение "плевать хотело" на языковые настройки винды
(эти настройки должны соответствовать настройкам сервера БД)

По округлению: можно написать самому. Если округлять до степеней 10, то работы на пару минут. Можете поискать на форуме, кажется тема уже обсуждалась.
Bond
Отправлено: 15.03.2005, 11:01


Станционный диспетчер

Группа: Участник
Сообщений: 142



С плавающей запятой в билдере нужно все делать ручками. У меня была проблема при сравнении чисел я в отладчике явно видел что условие выполняется, а программа так не думала. Пришлось умножать на 10 (необходимая точность) и обрезать дробную часть
telepath
Отправлено: 16.03.2005, 11:57


Станционный диспетчер

Группа: Участник
Сообщений: 132



А RoundTo не подходит?
Rius
Отправлено: 16.03.2005, 18:01


Мастер участка

Группа: Участник
Сообщений: 321



Если округлять для вывода в текстовом виде:
CODE
double x = 1.121545445;
Caption = FormatFloat("0.####e-000", x);

Замена , на .
CODE
int i;
AnsiString str = "1,545";
while((i=str.AnsiPos(",")) != 0) str.c_str[i-1] = '.';


Отредактировано Rius — 16/03/2005, 20:07
Gedeon
Отправлено: 16.03.2005, 18:17


Ветеран

Группа: Модератор
Сообщений: 1742



QUOTE (telepath @ 16/03/2005, 09:57)
А RoundTo не подходит?

Функция хорошая, но она появилась только в 6 и еще как бы не всегда всл используется.
Boyko
Отправлено: 18.03.2005, 12:51


Станционный диспетчер

Группа: Участник
Сообщений: 88



2 Rius

CODE
int i;
AnsiString str = "1,545";
while((i=str.AnsiPos(",")) != 0) str.c_str[i-1] = '.';


Ты думаешь что замена сделана в str? Читай Help на c_str()! cool.gif
AVC
Отправлено: 18.03.2005, 13:47


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

Ты думаешь что замена сделана в str? Читай Help на c_str()!


Ну не знаю. Делаю, например, так не один год, и все сходило с рук.
CODE

AnsiString line;
...
for (unsigned char *cp =(unsigned char*)line.c_str(); *cp; cp++)
   {  if        (*cp == 0xB3)  *cp = ListSeparator;
       else if (*cp == '.'     )  *cp = DecimalSeparator;
       else if (*cp == ' '     )  *cp = '0';
   }

** Rius
Отправлено: 18.03.2005, 14:50


Не зарегистрирован







QUOTE (Boyko @ 18/03/2005, 12:51)
2 Rius

CODE
int i;
AnsiString str = "1,545";
while((i=str.AnsiPos(",")) != 0) str.c_str[i-1] = '.';


Ты думаешь что замена сделана в str? Читай Help на c_str()!  cool.gif

Перевожу только специально для Тебя:
QUOTE
Returns the AnsiString converted to null-terminated character array.

char* __fastcall c_str() const;

Description

c_str returns a pointer a null-terminated character array containing the same characters as the AnsiString. If the AnsiString is unassigned, c_str returns an empty string (“”).

Usually, the value returned by c_str points to the internal character array referenced by the data property. This pointer is valid until the string is next modified (for example when the SetLength method is called or the AnsiString goes out of scope). However, if the internal array is NULL, c_str returns a pointer to a string literal.

The c_str method is intended primarily for reading the value of the AnsiString. To modify the string’s value, use the [] operator or AnsiString methods such as Insert and Delete.


QUOTE
Возвращает AnsiString, преобразованный к массиву символов с нулевым на конце (далее null-terminating).

char* __fastcall c_str() const;

Описание

c_str возвращает указатель на null-terminating массив символов, содержащий the те же символы, что и в AnsiString. Если AnsiString не назначен, c_str вернёт пустую строку (“”).

Обычно значение, возвращаемое c_str, указывает на внутренний массив символов, содержащийся в свойстве data. Этот указатель верен до тех пор, пока строка не будет модифицирована (например когда вызывается метод SetLength или AnsiString выходит из зоны видимости). Однако, если внутренний массив есть NULL, c_str возвращает указатель на строковую константу.

Метод c_str предназначен в основном для чтения значения AnsiString. Для модификации значения строки используйте оператор [] или методы AnsiString, такие как Insert и Delete.


Ещё вопросы будут? biggrin.gif
Георгий
Отправлено: 18.03.2005, 23:42


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



QUOTE (** Rius @ 18/03/2005, 14:50)
QUOTE (Boyko @ 18/03/2005, 12:51)
2 Rius

CODE
int i;
AnsiString str = "1,545";
while((i=str.AnsiPos(",")) != 0) str.c_str[i-1] = '.';


Ты думаешь что замена сделана в str? Читай Help на c_str()! cool.gif

QUOTE

Метод c_str предназначен в основном для чтения значения AnsiString. Для модификации значения строки используйте оператор [] или методы AnsiString, такие как Insert и Delete.


Ещё вопросы будут? biggrin.gif

всётаки не рекомендуется лезть во внутренний буфер AnsiString, а рекомендуется использовать operator[]
Rius
Отправлено: 19.03.2005, 13:54


Мастер участка

Группа: Участник
Сообщений: 321



CODE
while((i=str.AnsiPos(",")) != 0) str[i] = '.';
c_str()[], предполагаю, не сработало бы с мультибайтными символами
** Harold
Отправлено: 19.03.2005, 22:22


Не зарегистрирован







CODE

float fTmp = StrToFloat(eTempCenterZone->Text);
TVarRec args[3] = {5,1, fTmp };
eTempCenterZone->Text =Format("%*.*f", args, 2);

Типа, можно и знаки после запятой регулировать...
Я так делал — "спилил" из "дровишек" к применяемому мной железу.
Работает, и хорошо. А то напридумают ведь, заморочек на ровном месте... Правда, не знаю, это стандартная функция или нет...
Я последний раз писал прогу на ассемблере под Z80 — было все понятно, а сейчас — такое ощущение, что все языки расчитаны на непонимающих в "железе" людей... Такую ЧАЩУ всякой синтаксической ПУРГИ нужно преодолеть, что хочется поручить это кому-то другому, но, как верно замечает GEDEON — "Хочешь что-нибудь сделать хорошо — сделай это сам."(с) Хотя, психологи могут и поспорить с этим утверждением... wink.gif
Harold.

Отредактировано Георгий — 20/03/2005, 03:10
Boyko
Отправлено: 21.03.2005, 15:28


Станционный диспетчер

Группа: Участник
Сообщений: 88



QUOTE (** Rius @ 18/03/2005, 13:50)
QUOTE (Boyko @ 18/03/2005, 12:51)
2 Rius

CODE
int i;
AnsiString str = "1,545";
while((i=str.AnsiPos(",")) != 0) str.c_str[i-1] = '.';


Ты думаешь что замена сделана в str? Читай Help на c_str()! cool.gif

Перевожу только специально для Тебя:
QUOTE
Returns the AnsiString converted to null-terminated character array.

char* __fastcall c_str() const;

Description

c_str returns a pointer a null-terminated character array containing the same characters as the AnsiString. If the AnsiString is unassigned, c_str returns an empty string (“”).

Usually, the value returned by c_str points to the internal character array referenced by the data property. This pointer is valid until the string is next modified (for example when the SetLength method is called or the AnsiString goes out of scope). However, if the internal array is NULL, c_str returns a pointer to a string literal.

The c_str method is intended primarily for reading the value of the AnsiString. To modify the string’s value, use the [] operator or AnsiString methods such as Insert and Delete.


QUOTE
Возвращает AnsiString, преобразованный к массиву символов с нулевым на конце (далее null-terminating).

char* __fastcall c_str() const;

Описание

c_str возвращает указатель на null-terminating массив символов, содержащий the те же символы, что и в AnsiString. Если AnsiString не назначен, c_str вернёт пустую строку (“”).

Обычно значение, возвращаемое c_str, указывает на внутренний массив символов, содержащийся в свойстве data. Этот указатель верен до тех пор, пока строка не будет модифицирована (например когда вызывается метод SetLength или AnsiString выходит из зоны видимости). Однако, если внутренний массив есть NULL, c_str возвращает указатель на строковую константу.

Метод c_str предназначен в основном для чтения значения AnsiString. Для модификации значения строки используйте оператор [] или методы AnsiString, такие как Insert и Delete.


Ещё вопросы будут? biggrin.gif

2 Rius

Большое Спасибо за перевод! Вот что ты сам написал:

QUOTE

Метод c_str предназначен в основном для чтения значения AnsiString. Для модификации значения строки используйте оператор [] или методы AnsiString, такие как Insert и Delete.


используйте оператор [] для str, а не для str.c_str!!!!!!!!!
wink.gif

Что сказал господ-бог (компилятор) для str.c_str[i-1]="."?
Ответ:
E2235 Member function must be called or its address taken.

От меня:

c_str — функция (метод) и надо писать c_str()!!!!!!

Ещё ответы будут? biggrin.gif
Rius
Отправлено: 21.03.2005, 20:26


Мастер участка

Группа: Участник
Сообщений: 321



Boyko Это опечатка, я набирал код без проверки в билдере.
Смотри мой пост от 19/03/2005, 15:54 (GMT+05)

Конкретно я отвечал на вопрос
QUOTE
Ты думаешь что замена сделана в str? Читай Help на c_str()!

В хэлпе написано, что это возвращается указатель на внутренний буфер AnsiString (char[]), следовательно запись символа
CODE
str.c_str()[i] = '.';
заменит (i+1)ый символ строки, аналогично
CODE
str[i+1] = '.';

Так что замена сделана в str .
QUOTE
От меня:

c_str — функция (метод) и надо писать c_str()!!!!!!
Ну это мне и так известно уже давно, вот например пара ссылок из рамблера: 1, 2

Отредактировано Rius — 21/03/2005, 23:33
Георгий
Отправлено: 21.03.2005, 21:57


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



вы бы еще подрались
Guest
Отправлено: 22.03.2005, 16:51


Не зарегистрирован







smile.gif

Вернуться в Вопросы программирования в C++Builder