#delphi #floating-point
#строка #delphi #значение с плавающей запятой
Вопрос:
У меня есть испанский пользователь, который получает invalid floating point error
при выполнении этого
var
S : String;
R : Real;
begin
S := '3.12345';
R := StrToFloat(S); //- Exception here.
Причина этого в том, что его местоположение использует ,
для десятичного знака!
Как я могу безопасно преобразовать приведенную выше строку в значение с плавающей запятой для пользователя, чтобы она не взорвалась.
Комментарии:
1. Знаете ли вы (то есть на момент запуска программы) национальные настройки, используемые в строке?
2. Да, я делаю (причина, по которой это строка, заключается в том, что это ответ API).
Ответ №1:
Создайте свою собственную версию StrToFloat
function StrToFloat_UK(const AStr: string): Float;
var
FS: TFormatSettings;
begin
FS.Create('en-UK');
Result:= StrToFloat(AStr, FS):
end;
И используйте это вместо StrToFloat .
Комментарии:
1. Теперь я абсолютно не представляю, что вы делаете.
TFormatSettings
это запись, вы это знаете, верно?2. Из документации embarcadero: 1. Объявите переменную типа TFormatSettings. 2. Вызовите TFormatSettings. Создайте, чтобы заполнить переменную TFormatSettings информацией о локали. 3. Передайте переменную TFormatSettings в качестве последнего параметра процедуры форматирования строки.
3. Ну, у меня это не компилируется. И с каких пор вам нужна
Free
запись?! Возможно, вы используете более новую версию Delphi. В Delphi 2009 приведенный выше код является бессмыслицей…4. Хорошо, теперь я вижу, что эта запись изменилась со времен Delphi 2009. Delphi 2009 , Delphi XE Но, конечно, вы не должны
Free
использовать это даже в Delphi XE!
Ответ №2:
Используйте вторую перегрузку StrToFloat
с TFormatSettings
, для DecimalSeparator
которой .
установлено значение, равное.
Комментарии:
1. Я выбрал другой вместо вашего из-за исходного кода, но оба они почти одинаковы. Спасибо за ответ!
2. @Wizzard: Все в порядке. В любом случае я не мог понять, как инициализировать
TFormatSettings
. Прошло несколько лет с тех пор, как я работал с Object Pascal, и мне никогда не приходилось сталкиваться с этим; этот ответ был в основном результатом быстрого поиска в Интернете (и я был совершенно уверен, что каждая функция синтаксического анализа, чувствительная к локали, должна иметь возможность заранее настроить язык для использования).
Ответ №3:
Вы могли бы использовать процедуру val
, она игнорирует настройки локальной системы.
var
S : String;
R : Real;
Test: Integer;
begin
S := '3.12345';
Val(S, R, Test);
end;
Комментарии:
1. Классный трюк. Но я надеюсь, что значение Val не ограничено только реальным типом и отлично работает с Double . Надеюсь, есть перегрузки для double?
2. Также работает с удвоениями и целыми числами. Само по себе оно не перегружено, это магия компилятора.
Ответ №4:
Если вы знаете, что строки используют .
в качестве десятичного разделителя, то вам следует сделать что-то вроде
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.UpdateFormatSettings := false;
DecimalSeparator := '.';
end;
Строка
Application.UpdateFormatSettings := false;
очень важно. Значение по умолчанию этого свойства равно true
, и в таком случае DecimalSeparator
переменная может быть возвращена к своему значению по умолчанию (например, ,
) в любое время, например, при смене пользователя.
Комментарии:
1. Избегайте использования глобального
DecimalSeparator
для этого, так как вы не будете знать, какие другие единицы зависят от этого (и которые сломаются). Лучше использовать локальныйTFormatSettings
экземпляр.2. -1: Игнорировать пользовательские настройки для всего в вашем приложении — это неправильный путь, особенно когда вы можете использовать перегруженную версию, о чем сообщают Джоуи и Йохан.