Ошибка в преобразовании String to Real

Форум для программистов

Сообщение Strateg » Вт май 31, 2005 12:43 pm

На дельфи 7 пишу программу. Есть строка '1112.28'. Преобразую ее в Real. Вывожу результат в файл - получается 1112.27999999.
Проверяю по шагам. Преобразовал в Real - получил 1112.28, все красиво. Взял дробную часть, умножил на 100 (присвоил в переменную temp1. В ней (смотрю) - получается 28), откинул от полученного дробную часть (поместил результат в переменную temp2, смотрю - тоже 28). Обе переменные имеют тип Real. Вычитаю: temp2 - temp1 и получаю что-то типа = 3.5*10^(-15). Это как понимать??? Откуда??? Кто-нить сталкивался?
У меня кипят мозги. Такого не бывает. Подскажите, как избежать такой беды?
хм...!
Strateg
Полковник
 
Сообщений: 1016
Зарегистрирован: Пт май 24, 2002 7:26 am
Откуда: Краснодар
Пункты репутации: 0

Сообщение Elzor » Вт май 31, 2005 1:28 pm

Бывает.
Немного теории:
Любое число в Real хранится с какой-то точность. Это связано с тем, что реально оно хранится в двоичной системе счисления. То есть любое преобразование Integer->Real, String->Real и т.д. производится с какой-то точностью. 3.5*10^(-15) - это и есть эта точность. Просто при выводе на экран автоматически производится округление, а при преобразовании в строку - нет. Вот и все.
Избежать - никак. Можно попробывать написать свою процедуру вывода в файл где Real числа (насколько я понял файл у тебя текстовый) преобразовывать в строку с точностью до 7 знака после запятой.
<span style='color:purple'>Люди не знают, что лисы умеют лазить по деревьям, если очень сильно захотят. Вот белки - те знают.</span><span style='color:gray'> (с) П.Бигл</span>
--------------------
<a href='http://foobar2000.ru/forum/' target='_blank'>Новый Оффорум Foobar2000</a>
--------------------
<a href='http://wincmd.ru/download.php?id=neropanel' target='_blank'>Neropanel</a> - плагин для записи CD из TC, используя NeroAPI <a href='http://www.fforum.ru/index.php?showtopic=19193&hl=' target='_blank'>обсуждение плагина</a>
--------------------
<a href='http://www.spikelee.fatal.ru' target='_blank'>Изображение</a>
Elzor
Полковник
 
Сообщений: 1157
Зарегистрирован: Пт дек 24, 2004 2:59 pm
Откуда: Орск
Пункты репутации: 0

Сообщение Sh0Ck_filE » Вт май 31, 2005 3:32 pm

2Strateg
Хотя бы из принципа - попробуй сделать то же самое на FreePascal, или на другом компилере ;) Дельфи - она такая странная... :)
<!--coloro:red--><span style="color:red"><!--/coloro-->"Для того чтобы быть человеком, надо им какое-то время не быть."<!--colorc--></span><!--/colorc--> ©<a href="http://zhurnal.lib.ru/b/brigadir_j_a/" target="_blank">Ю. А. Бригадир.</a>
<a href="http://counter.li.org/cgi-bin/runscript/display-person.cgi?user=437143" target="_blank">Registered Linux user #437143</a>.
Sh0Ck_filE
Генерал-лейтенант
 
Сообщений: 3474
Зарегистрирован: Пн апр 21, 2003 6:20 pm
Откуда: СССР
Пункты репутации: 0

Сообщение RAVen42 » Ср июн 01, 2005 12:32 am

<!--emo&:blink:-->[img]style_emoticons/<#EMO_DIR#>/blink.gif[/img]<!--endemo--> Странно я пишу на Делфи 6 и не чего подобного не происходит. Интереса ради дажеть своял небольшой пример, всё нормально работает.
Программер просто Программер
RAVen42
Подполковник
 
Сообщений: 725
Зарегистрирован: Пт авг 27, 2004 1:04 am
Откуда: Кемерово
Пункты репутации: 0

Сообщение Elzor » Ср июн 01, 2005 4:16 am

Как говориться, зависит от реализации компилятора.
<span style='color:purple'>Люди не знают, что лисы умеют лазить по деревьям, если очень сильно захотят. Вот белки - те знают.</span><span style='color:gray'> (с) П.Бигл</span>
--------------------
<a href='http://foobar2000.ru/forum/' target='_blank'>Новый Оффорум Foobar2000</a>
--------------------
<a href='http://wincmd.ru/download.php?id=neropanel' target='_blank'>Neropanel</a> - плагин для записи CD из TC, используя NeroAPI <a href='http://www.fforum.ru/index.php?showtopic=19193&hl=' target='_blank'>обсуждение плагина</a>
--------------------
<a href='http://www.spikelee.fatal.ru' target='_blank'>Изображение</a>
Elzor
Полковник
 
Сообщений: 1157
Зарегистрирован: Пт дек 24, 2004 2:59 pm
Откуда: Орск
Пункты репутации: 0

Сообщение RAVen42 » Ср июн 01, 2005 4:45 am

Elzor Раз уж речь пошла о компиляторе. Можеть ты подскажешь где можно нарыть инфы по компилятору. Что то поискал я в инете и нечего стоещего не нашел
Программер просто Программер
RAVen42
Подполковник
 
Сообщений: 725
Зарегистрирован: Пт авг 27, 2004 1:04 am
Откуда: Кемерово
Пункты репутации: 0

Сообщение Elzor » Ср июн 01, 2005 4:54 am

А что тебя интересует? Как написать свой? Опции? Общие принципы работы? По D7, сразу говорю, у меня никакой информации нет, всю жизнь на BCB писал, там кой-какие отличия таки есть.
<span style='color:purple'>Люди не знают, что лисы умеют лазить по деревьям, если очень сильно захотят. Вот белки - те знают.</span><span style='color:gray'> (с) П.Бигл</span>
--------------------
<a href='http://foobar2000.ru/forum/' target='_blank'>Новый Оффорум Foobar2000</a>
--------------------
<a href='http://wincmd.ru/download.php?id=neropanel' target='_blank'>Neropanel</a> - плагин для записи CD из TC, используя NeroAPI <a href='http://www.fforum.ru/index.php?showtopic=19193&hl=' target='_blank'>обсуждение плагина</a>
--------------------
<a href='http://www.spikelee.fatal.ru' target='_blank'>Изображение</a>
Elzor
Полковник
 
Сообщений: 1157
Зарегистрирован: Пт дек 24, 2004 2:59 pm
Откуда: Орск
Пункты репутации: 0

Сообщение earl » Ср июн 01, 2005 5:26 am

2Strateg : А какой ты функцией пользуешься?
Код: выделить все
Var C : Real;
     S : String;
Begin
C : 1112.28;
S := FloatToStr(C);
Caption := S;
Str(C:4:2, S);
Caption := Caption + ' - ' + S;

Ну, и обратное преобразование соответственно.
Обе одинаковую... "ошибку" дают? Кстати, у меня (Delphi7) обе из этих функций такого результата не дают, всё точно - как в оригинальной переменной... <!--emo&:unsure:-->[img]style_emoticons/<#EMO_DIR#>/unsure.gif[/img]<!--endemo-->
Последний раз редактировалось earl Ср июн 01, 2005 5:27 am, всего редактировалось 1 раз.
earl
Подполковник
 
Сообщений: 614
Зарегистрирован: Ср июн 19, 2002 7:04 pm
Откуда: Череповец
Пункты репутации: 0

Сообщение Strateg » Ср июн 01, 2005 1:35 pm

2earl
Во! Меня аж совесть мучила задавать такой вопрос. Я помню, что есть операторы, позволяющие задавать формат данных. Преобразование в строку числа определенным форматом (например :15:2) можно задать оператором Str, а каким это можно сделать оператором в обратную сторону? Из строки в число, то-есть стопроцентно откинуть все левое, что "дальше" второго знака после запятой? Я пытался разобраться, но не нашел ни упомянутого оператора, ни варианта, как можно создать свой тип данных с друмя знаками после запятой. Если знаете, подскажите.
// зачем мне это? я складываю (как правильно говорили - беру цифры из текстовика) много значений. и видимо та самая погрешность превращается в реальное число. Пока в проге сделал округление, но это извращенческий способ решения проблемы. При пошаговой проверке в переменной показывается, что содержится число без этой погрешности.

Кста, попробовал другой вариант: Число, только преобразованное в Real из String я умножаю на 100, потом от него оператором Int беру целую часть и складываю все, потом результат (сумму) делю на 100 и получаю вообще левое число (в десятых единицах разнится с тем, что реально должно получиться.). Тут-то откуда погрешность???
Последний раз редактировалось Strateg Ср июн 01, 2005 1:46 pm, всего редактировалось 1 раз.
хм...!
Strateg
Полковник
 
Сообщений: 1016
Зарегистрирован: Пт май 24, 2002 7:26 am
Откуда: Краснодар
Пункты репутации: 0

Сообщение SiMM » Ср июн 01, 2005 4:13 pm

<!--QuoteBegin-Strateg+Jun 1 2005, 17:35--><div class='quotetop'>QUOTE(Strateg @ Jun 1 2005, 17:35)</div><div class='quotemain'><!--QuoteEBegin-->Пока в проге сделал округление, но это извращенческий способ решения проблемы<!--QuoteEnd--></div><!--QuoteEEnd-->Это единственноправильный способ решения проблемы. Разве что тебя не угораздит написать библиотеку, работающую, к примеру, хотя бы с BCD-представлением чисел. Но это извращение.<!--QuoteBegin-Strateg+Jun 1 2005, 17:35--><div class='quotetop'>QUOTE(Strateg @ Jun 1 2005, 17:35)</div><div class='quotemain'><!--QuoteEBegin-->При пошаговой проверке в переменной показывается, что содержится число без этой погрешности.<!--QuoteEnd--></div><!--QuoteEEnd-->Потому что среда, в которой ты выполняешь вывод числа при отладке, выполняет округление ("дружественность", которая тебя подводит).<!--QuoteBegin-Strateg+Jun 1 2005, 17:35--><div class='quotetop'>QUOTE(Strateg @ Jun 1 2005, 17:35)</div><div class='quotemain'><!--QuoteEBegin-->Число, только преобразованное в Real из String я умножаю на 100, потом от него оператором Int беру целую часть и складываю все, потом результат (сумму) делю на 100 и получаю вообще левое число (в десятых единицах разнится с тем, что реально должно получиться.)<!--QuoteEnd--></div><!--QuoteEEnd-->Другой вариант называется "работа с фиксированной запятой", в отличии от "оригинального" варианта - работа с числами с плавающей запятой.<!--QuoteBegin-Strateg+Jun 1 2005, 17:35--><div class='quotetop'>QUOTE(Strateg @ Jun 1 2005, 17:35)</div><div class='quotemain'><!--QuoteEBegin-->Тут-то откуда погрешность???<!--QuoteEnd--></div><!--QuoteEEnd-->Попробуй десятичное число 0.01 перевести в двоичную систему счисления и обратно (деление на 100 это тоже самое, что умножение на 0.01). Будешь поражён. Ещё на первом этапе. Когда попытаешься перевести 0.01 в двоичную. Ибо получишь периодическую дробь. Машина же не умеет хранить периодических дробей. Как и других извратов типа числа Pi или e. Поэтому она хранит их с конечной точностью. Естесственно, после того, как ты попытаешься перевести КОНЕЧНОЕ двоичное число обратно в десятичную систему, ты уже не получишь оригинала. Простой пример, показывающий, что ошибка может возникнуть уже на этапе перевода десятичного, понятного человеку числа, в машинное представление.
А вообще я поражаюсь, господа программисты. Это - азы программирования и машинной арифметики при действиях с числами с плавающей запятой. И их надо бы знать.
IRC: <a href='http://www.fileforum.ru/irc.php' target='_blank'>RUSNET #fileforum</a> (irc.tsk.ru:6669)
SiMM
Подполковник
 
Сообщений: 588
Зарегистрирован: Чт июн 13, 2002 8:41 am
Пункты репутации: 0

Сообщение RAVen42 » Чт июн 02, 2005 12:27 am

Интересно а что есть нового в Делфи ? что нет в 6-ой версии???
Как мне кажеться если возникают такие геморои, а расчеты нужны точные не лучше ли поставить Делфик 6. Да и не париться.
Илинакряйняк написать самую простую функцию для округления. И не заморачиваться. Или на крайний случай напиши компанент свой который бы округления делал и не париться.
Программер просто Программер
RAVen42
Подполковник
 
Сообщений: 725
Зарегистрирован: Пт авг 27, 2004 1:04 am
Откуда: Кемерово
Пункты репутации: 0

Сообщение Strateg » Чт июн 02, 2005 6:21 am

Уфф!! Спасибо, парни! Я разобрался в проблеме.
2SiMM
у меня экономическое образование. Прикладную информатику счас изучаю заочно, но частенько знаю больше преподов. Не хочется натыкаться так на проблему каждый раз. Потому про азы программирования - интересно, какие еще есть азы и где их можно почерпнуть?
Последний раз редактировалось Strateg Чт июн 02, 2005 6:23 am, всего редактировалось 1 раз.
хм...!
Strateg
Полковник
 
Сообщений: 1016
Зарегистрирован: Пт май 24, 2002 7:26 am
Откуда: Краснодар
Пункты репутации: 0

Сообщение Ciber SLasH » Ср окт 26, 2005 9:26 pm

<!--QuoteBegin-Strateg+Jun 2 2005, 10:21--><div class='quotetop'>QUOTE(Strateg @ Jun 2 2005, 10:21)</div><div class='quotemain'><!--QuoteEBegin-->какие еще есть азы и где их можно почерпнуть?
[right][snapback]176403[/snapback][/right]
<!--QuoteEnd--></div><!--QuoteEEnd-->
Вот здесь поподробнее: <a href='http://www.delphikingdom.com/asp/viewitem.asp?catalogID=374' target='_blank'>http://www.delphikingdom.com/asp/viewitem.asp?catalogID=374</a>
Ciber SLasH
Майор
 
Сообщений: 314
Зарегистрирован: Пн ноя 24, 2003 11:28 am
Откуда: Питер
Пункты репутации: 0

Сообщение Strateg » Чт окт 27, 2005 12:38 pm

2Ciber SLasH
спасибо, интересно.
хм...!
Strateg
Полковник
 
Сообщений: 1016
Зарегистрирован: Пт май 24, 2002 7:26 am
Откуда: Краснодар
Пункты репутации: 0

Сообщение Ciber SLasH » Пн окт 31, 2005 4:01 am

2Strateg:
Пожалуйста :)
Ciber SLasH
Майор
 
Сообщений: 314
Зарегистрирован: Пн ноя 24, 2003 11:28 am
Откуда: Питер
Пункты репутации: 0


Вернуться в Программирование

Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 14

cron