Текущий архив: 2003.06.30;
Скачать: CL | DM;
Вниз
Вещественные числа... Найти похожие ветки
← →
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;
Скачать: CL | DM;
Память: 0.52 MB
Время: 0.007 c