Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.03.04;
Скачать: CL | DM;

Вниз

Single   Найти похожие ветки 

 
Fast   (2002-02-15 18:40) [0]

Для эконими памяти и места в файле куда надо сохранять данные вместо типа Real я использовал Single.
Наткнулся на пародокс

r:real;
s:single;
begin
r:=StrToFloat(edit1.text);
s:=r;
if s=r then ShowMessage("Это никогда не сработает");
end;


Тоесть если я ввожу r=0.3 то s=0.30000001192 - откуда берутся лишние знаки?
и почему Single в результате всегда болше Real.


 
Иван Шихалев ©   (2002-02-15 18:44) [1]

А можно привести и Single и Real? А то "нас сомненья гнетут". Хотя в погрешности округления ничего удивительного нет.


 
Fast   (2002-02-15 18:50) [2]

Предлогаешь сделать так?

begin
r:=StrToFloat(edit1.text);
s:=StrToFloat(edit1.text);
if s=r then ShowMessage("Это никогда не сработает");
end;


Результат тот-же.


 
Иван Шихалев ©   (2002-02-15 18:54) [3]

Да нет. :0

Сомненья, честно говоря, насчет всегда.

А причина вообще-то проста: не может 0.3 с одной точностью быть равно 0.3 с другой точностью в двоичной системе счисления. Вот и все.


 
Fast   (2002-02-15 18:56) [4]

Мне бы черт с ним с Real....
Просто почему StrToFloat() в Single переводит с погрешностю?
а вот в Real нет.
если кто не до конца понял то бюсь я над тем как из string Line:="0,3" получить s=0,3 a не s=0.30000001192.


 
Иван Шихалев ©   (2002-02-15 19:03) [5]

И в Single, и в Real с погрешностью... Ну не влазит точное двоичное представление 0.3 в любое конечное число бит.


 
Fast   (2002-02-15 19:12) [6]

Не веришь?
Проверь.
Вот тебе тестовый код (надо два Listbox"a, батон и edit).

procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
r:real;
s:single;
begin
r:=StrToFloat(edit1.text);
s:=StrToFloat(edit1.text);
ListBox1.Items.Add(FloatToStr(s));
ListBox2.Items.Add(FloatToStr(r));
if s=r then ShowMessage("Это никогда не сработает");
end;

Я предпологаю что Delphi округляет Real но чем ей плох Single
(это уже не четыре байта разницы это ворос)



 
Фэ ©   (2002-02-15 21:09) [7]

Для корректного сравнения Real типов (Single, Double(Real), Extended,..) как правило вводят константу E равную желаемой точности сравнения.

Вот пример

function IsEqualDouble_(f1, f2, E: extended): boolean;
begin
Result := (abs(f1-f2) < E);
end;

Либо сравнивают до N-го дес.разряда


 
Юрий Зотов (M) ©   (2002-02-15 21:10) [8]

> Fast

Пусть мы делим 1000 на 999. Результат есть бесконечная дробь, которая не может уместиться в любое конечное число десятичных разрядов. Давайте посмотрим, какое строковое представление результата мы получим, задавая для него разную длину (то есть, отводя под него разное число разрядов):

3 цифры - 1.00
5 цифр - 1.0010
7 цифр - 1.001001

Почему так? Ведь число-то всегда одно и то же, а его изображения разные. Очевидно, все дело в том, какую длину разрядной сетки мы отводим под это число - то есть, где мы его "обрезаем".

То же самое происходит и у Вас. В памяти числа хранятся в двоичной системе счисления, а в ней 0.3 - это бесконечная дробь. Значит, поскольку Real, Single, Double и Extended имеют разное количество двоичных разрядов, одно и то же десятичное число 0.3 фактически будет РАЗНЫМ двоичным числом для каждого из этих типов. Что Вы и наблюдаете.

Прочитайте на "Королевстве" статью Антона Григорьева "Неочевидные особенности вещественных чисел" - многие вопросы исчезнут.




Страницы: 1 вся ветка

Текущий архив: 2002.03.04;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.011 c
1-9207
knyaz17
2002-02-12 12:01
2002.03.04
Как вставить в Word текст из буфера обмена?


14-9275
dimonf
2002-01-16 20:20
2002.03.04
Если кто из Кирова (обл.)?


1-9185
fag2000@ok.ru
2002-02-14 13:59
2002.03.04
Файлы отображаемые в память


1-9215
forrest1
2002-02-15 09:57
2002.03.04
Развернуть узел дерева с помощью клавиатуры


1-9134
pakko
2002-02-15 21:24
2002.03.04
Простой вопрос!