Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.06.30;
Скачать: [xml.tar.bz2];

Вниз

Вещественные числа...   Найти похожие ветки 

 
Viktoria   (2003-06-16 11:20) [0]

Добрый день уважаемые Мастера!

Помогите пожалуйста разобраться с вещественными числами.

Я получила задание, в котором необходимо в теле цикла представить следующее

procedure TForm1.Button1Click(Sender: TObject);
var S:Single;
begin
S:=0;
while S<=0.1 do begin
Memo1.Lines.Add(floattostr(S));
S:=S+0.01;
end;
end;

К сожалению переменная должна быть обязательно типа Single
(Currency и Double к примеру меня полностью выручили, но их нельзя использовать :((( )

После прогона цикла получаю

0
0,00999999977648258
0,0199999995529652
0,0299999993294477
0,0399999991059303
0,0500000007450581
0,0600000023841858
0,0700000002980232
0,0799999982118607
0,0899999961256981
0,0999999940395355

Еще в моем задании сказано, что значения переменной были получены с точностью до 4 знаков,
после запятой.

Подскажите как обработать числа с такой точностью, как обрезать хвост, который представляется
у меня после запятой.

К сожалению я, не очень хорошо умею работать с вещественными числами.

Никаких статей по этому поводу не нашла, видела только статьи по проблематике, но по
решению конкретных задач не встречала.

Пожалуйста не смейтесь надо мной, но я даже не могу выделить следующие составляющие из вещественного
числа:

Знак Экспонента Мантисса

А что говорить уже о сравнении чисел с необходимой точностью.

Если кто чем может, помогите пожалуйста.
Любая помощь приветствуется.


 
icWasya   (2003-06-16 11:23) [1]

Memo1.Lines.Add(FormatFloat("0.0000",S));


 
Skier   (2003-06-16 11:25) [2]


> Никаких статей по этому поводу не нашла, видела только статьи
> по проблематике, но по
> решению конкретных задач не встречала.

http://www.delphikingdom.com/helloworld/reals.htm
+ FloatToStrF(...)


 
Viktoria   (2003-06-16 11:30) [3]


> icWasya © (16.06.03 11:23)
> Memo1.Lines.Add(FormatFloat("0.0000",S));


Это уже представление числа на выходе, а в программе оно так и остается не преобразовынным.



> http://www.delphikingdom.com/helloworld/reals.htm
> + FloatToStrF(...)


Статью эту читала, но она только описывает проблему.


 
Skier   (2003-06-16 11:34) [4]

>Viktoria © (16.06.03 11:30)

> Статью эту читала, но она только описывает проблему.

"Знать проблему значит на половину её решить" :)


> Это уже представление числа на выходе, а в программе оно
> так и остается не преобразовынным.

Да. Оно занимает 10 байт и является Extended.


 
Viktoria   (2003-06-16 11:34) [5]

Очень прошу помогите разобраться с разложением числа, т.е. извлечением из переменной типа Single, её мантису, знак и экспоненту.


 
Skier   (2003-06-16 11:37) [6]

Милая барышня, а Вы вообще внимательно смотрели на
функцию FloatToStrF(...) и её параметры ?


 
alexvan   (2003-06-16 11:49) [7]

FloatToStrF(Value: Extended; Format: TFloatFormat; Precision, Digits: Integer): String;

type
TFloatFormat = (ffExponent, ffFixed, ffGeneral, ffNumber, ffCurrency);


 
Viktoria   (2003-06-16 12:40) [8]


> Skier © (16.06.03 11:37)
> Милая барышня, а Вы вообще внимательно смотрели на
> функцию FloatToStrF(...) и её параметры ?


> alexvan © (16.06.03 11:49)
> FloatToStrF(Value: Extended; Format: TFloatFormat; Precision,
> Digits: Integer): String;
>
> type
> TFloatFormat = (ffExponent, ffFixed, ffGeneral, ffNumber,
> ffCurrency);


Да но эта функиция переводит вещественное число в строку,
в принципе извлечь отсюда можно всё, что угодно.

Но как же быть с моим заданием

> Еще в моем задании сказано, что значения переменной были
> получены с точностью до 4 знаков,
> после запятой.


var S:Single;
begin
S:=0.1;
if S=0.1 then begin
end;


Проверок подобного типа не провести со строкой.
Или просто необходимо проверить два числа

if Singl1=Singl2 then ...

С точностью 4-х знаков после запятой.

Может условие можно изменить как-то?

Помогите пожалуйста.


 
alexvan   (2003-06-16 12:44) [9]

Я не совсем понял суть задания. Но строку-то тоже можно вернуть обратно StrToFloat()


 
Skier   (2003-06-16 12:45) [10]


> Или просто необходимо проверить два числа
>
> if Singl1=Singl2 then ...

Именно так и делай !


 
Skier   (2003-06-16 12:50) [11]


> значения переменной были
> > получены с точностью до 4 знаков,
> > после запятой.

Были получены в строке.
Как же ещё ты из получишь ?! :)
Или я что-то не понимаю ?


 
Viktoria   (2003-06-16 14:13) [12]

Singl1 - переменная эталон.

К примеру:

0.0001

А Singl2 - переменная которая получена

0.00013

При сравнении таких чисел мы равно не получим, но так как по заданию точность у нас 4 десятичных цифры, значит остальное нужно обнулить, чтобы Singl2 тоже получилась 0.000100000000...

Насколько я поняла нужно два раза перед тем как Singl2 передать в условие, сделать
FloatToStrF (обрезать) и
StrToFloat и только потом уже передавать...

Но можно ли изменить условие так, чтобы проверка осуществлялась должным образом, без ошибок, и чтобы StrTo два раза не вызывать?


 
Skier   (2003-06-16 14:22) [13]

>Viktoria © (16.06.03 14:13)
Можно поиграться с управляющим словом сопроцессора,
т.е. с 8 и 9 битами этого слова
(Если ты читала статью ты знаешь о чём речь).
Только не забудь потом восстановить всё как было
(используй try-finally-end)


 
icWasya   (2003-06-16 15:52) [14]

>... просто необходимо проверить два числа
> if Singl1=Singl2 then ...
>С точностью 4-х знаков после запятой.

if (abs(Singl1-Singl2)<0.0001 then ...



 
_ALEXey_   (2003-06-16 16:52) [15]

А если так проверять: If Trunc(Singl1*10000)=Trunc(Singl2*10000) then ......

Экспонетна: Trunc(Singl1)
Мантисса: Frac(Singl1)
Знак: If Singl1 < 0
then <значит "минус">
else <значит "плюс">;


По-моему должно работать, если я правильно понял задание.


 
Anatoly Podgoretsky   (2003-06-16 17:12) [16]

Viktoria © (16.06.03 11:30)
А в программе и не получится, это же числа с плавающей запятой, а не с фиксированной.
Жталоном являяется число 0,02 - его как не окнугляй все равно 0,02 никогда не получишь, а только 0,02+-дельта


 
Александр-И   (2003-06-16 17:58) [17]

В модуле Math есть такие функции и процедуры:
1. function RoundTo(const AValue: Double; const ADigit: TRoundToRange): Double; - округление вещественных чисел до заданной точности.
2. procedure Frexp(const X: Extended; var Mantissa: Extended; var Exponent: Integer; - Вычисление мантиссы и порядка заданной величины/
3. Учтите матчасть, милая барышня!



 
Александр-И   (2003-06-16 18:06) [18]

Ваш пример:

procedure TForm1.Button1Click(Sender: TObject);
var S:Single;
E:Extended;
begin
S:=0;
E:=S;
while S<=0.1 do begin
E:=RoundTo(S,-4);
Memo1.Lines.Add(floattostr(E));
S:=S+0.01;
end;
end;


 
Viktoria   (2003-06-16 18:12) [19]


> Anatoly Podgoretsky © (16.06.03 17:12)
> Viktoria © (16.06.03 11:30)
> А в программе и не получится, это же числа с плавающей запятой,
> а не с фиксированной.
> Жталоном являяется число 0,02 - его как не окнугляй все
> равно 0,02 никогда не получишь, а только 0,02+-дельта


А откуда вы взяли такой эталон?
Мне не совсем понятно.


 
Anatoly Podgoretsky   (2003-06-16 21:07) [20]

Опытном путем, на самом деле конечно не только это число, а любое производное от него, деленое/умноженное на 2^N, что равносильно сдвину порядка на один разряд, просто подобное число невозможно представить в виде двоичной дробе, как нельзя представить 1/3 в виде десятичноей дроби. Его подлая сущность проясляется очень наглядно для Single, для другой точности тоже самое, только наблюдать надо отладчиком, поскольку при выводе производится округление.


 
Viktoria   (2003-06-16 22:54) [21]


> Anatoly Podgoretsky © (16.06.03 21:07)
> Опытном путем, на самом деле конечно не только это число,
> а любое производное от него, деленое/умноженное на 2^N,
> что равносильно сдвину порядка на один разряд, просто подобное
> число невозможно представить в виде двоичной дробе, как
> нельзя представить 1/3 в виде десятичноей дроби. Его подлая
> сущность проясляется очень наглядно для Single, для другой
> точности тоже самое, только наблюдать надо отладчиком, поскольку
> при выводе производится округление.


А можно примерчик? Расскажите пожалуйста, как вы наблюдаете это через отладчик?

Выше приводилось много различных вариантов, что вообще можно сделать с вещественными числами. Насколько я правильно всех поняла получается, что для проверок условий, и установки точности можно использовать примеры которые были представлены выше. Но и более чем проверок, что мне и нужно было в задании.


> if (abs(Singl1-Singl2)<0.0001 then ...


Этот мне кажется наиболее применительным, так как позволяет варьировать различной точностью.

А если говорить про неправильные двоичные дроби, то если я вас правильно поняла, то округляй я 0.02 до 3-х чисел, 5-ти и т.д.,
все равно на выходе будет неправильная дробь. Таким образом, мои первые предположения об округлении функциями FloatToStrF были неверны.

Всех хочу поблагодарить, за то, что приняли участие и помогли мне разобраться.

Если у кого-то еще есть подобные схемы проверок в условиях, циклах и т.д., то со своей стороны я была бы очень признательна за любую помощь.



 
Anatoly Podgoretsky   (2003-06-17 08:02) [22]

Ну поступим проще
var
S: Single;
begin
S := 0.02;
Label1.Caption := FloatToStr(S);
S := Trunc(S*100)/100; // часто рекомендуют именно этот путь
Label2.Caption := FloatToStr(S);
end;

Поставь точку останова на первой строке, а на S нажми F5 и дальше по шагам наблюдай в окне отладчика значения переменной, тоже проделай для Double и Extended


 
Anatoly Podgoretsky   (2003-06-17 09:48) [23]

Вот еще один наглядный пример "округления" до двух знаков


procedure TForm1.Button1Click(Sender: TObject);
var
I : Integer;
S : Single;
D : Double;
E : Extended;
begin
S := 0;
D := 0;
E := 0;
for I := 1 to 100 do begin
S := Trunc((S + 0.02) * 100) / 100;
D := Trunc((D + 0.02) * 100) / 100;
E := Trunc((E + 0.02) * 100) / 100;
Memo1.Lines.Add(FloatToStr(S));
Memo2.Lines.Add(FloatToStr(D));
Memo3.Lines.Add(FloatToStr(E));
end;
Label1.Caption := FloatToStr(S);
Label2.Caption := FloatToStr(D);
Label3.Caption := FloatToStr(E);
end;


 
Viktoria   (2003-06-17 13:35) [24]


> Anatoly Podgoretsky © (17.06.03 09:48)


Результат выполнения первой программы

Label1 - 0,0199999995529652
Label2 - 0,00999999977648258

Результат выполнения второй программы

Для Single

...
1,39999997615814
1,4099999666214
1,41999995708466
1,42999994754791

Для Double

...
1,43
1,44
1,45

Для Extended

...
1,81
1,83
1,85

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

Во втором случае наглядно видно на Single...

Подскажите пожалуйста, как вызвать отладчик, когда поставлен Break Point и идет трассировка.




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

Форум: "Основная";
Текущий архив: 2003.06.30;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.007 c
4-97930
xZero
2003-04-28 19:06
2003.06.30
Thread


1-97727
PI{}Puk
2003-06-18 10:25
2003.06.30
Потоки


14-97825
Саня
2003-06-08 11:14
2003.06.30
Какие компоненты


11-97578
Alexander
2002-10-16 13:35
2003.06.30
Как можно написать что-то подобное Sleep(msek) с обработкой всех


3-97512
me2
2003-06-05 17:13
2003.06.30
Сортировка полей таблицы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский