Linux за българи: Форуми

Програмиране => Общ форум => Темата е започната от: c111100101 в May 14, 2010, 17:05



Титла: Java и загуба на точност при сумиране на float
Публикувано от: c111100101 в May 14, 2010, 17:05
Простете може би за тъпия въпрос за някой, но как се решава проблема със загубата на точност в следния случай:
Код:
float sum = 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f;

Резултата е 1.0000001

Примерно в Python, този проблем не съществува. :)


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: b2l в May 14, 2010, 17:17
Що не пробваш с double?


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: bop_bop_mara в May 14, 2010, 17:26
Не е баш така, при това на никой език. В частност ето проба с Python:
Код
GeSHi (Bash):
  1. mara@OVNIWatermelon:~$ python
  2. Python 2.5.5 (r255:77872, Apr 21 2010, 08:40:04)
  3. [GCC 4.4.3] on linux2
  4. Type "help", "copyright", "credits" or "license" for more information.
  5. >>> a=0
  6. >>> a
  7. 0
  8. >>> a=0.0
  9. >>> a
  10. 0.0
  11. >>> a=3.0
  12. >>> a
  13. 3.0
  14. >>> a=9.999999999999999999
  15. >>> a
  16. 10.0
  17. >>> a=6.785932526
  18. >>> a
  19. 6.7859325259999999
  20. >>>

Аритметиката с плаваща запетая никога не е точна, независимо на кой език пишеш. Затова винаги, когато проверяваш дали са равни две числа с плаваща запетая, сравнявай дали абсолютната стойност на разликата им е по малка от някакво мъничко число от рода на 1е-6 или по-малко.

ПС. Верно в Java беше малко по-видимо (не знам точно защо), но по принцип това поведение си е универсално.


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: c111100101 в May 14, 2010, 17:42
Що не пробваш с double?
Код:
double suma = 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d;

Резултат: 0.9999999999999999


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: bop_bop_mara в May 14, 2010, 17:42
Чисто математически 0.(9) (0 цяло и 9 в период) е 1, освен всичко :)


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: romeo_ninov в May 14, 2010, 17:43
И само да допълня че доколкото имам спомени точно 0.1 няма точно представяне във формат с плаваща запетая


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: c111100101 в May 14, 2010, 18:21
Проблема е, че числата се представят в краен брой битове и от там идва загубата, колкото и малка да е тя. Интересува ме по скоро как тази загуба реално се отразява в практиката?
Възможно ли е да възникнат проблеми вследствие на тази загуба и как се отстраняват?
Или примерно ако сега си стартирам калкулатора на компютъра и събера десет пъти 0.1 получавам точно 1. Как примерно е програмиран калкулатора, че да вади резултат без загуба?


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: task_struct в May 14, 2010, 18:36
Проблема с точноста при компютърната аритметика е доста срещан, аз лично се боря с него почти всеки ден :(

Реално калкулатора също получава числото с грешка, но използва алгоритъм за отстраняването и.
Всяка сметка се извършва с някаква точност. Всичко след тази точност се отрязва или закръглява (нагоре или надолу)


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: c111100101 в May 14, 2010, 18:38
Всъщност и в Python го има проблема, ето го и теста:  :)
Код:
>>> a = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1
>>> a
0.99999999999999989
>>> a = 0.99999999999999989
>>> a
0.99999999999999989
>>>


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: c111100101 в May 14, 2010, 19:02
Ето и нещо интересно по темата но за C++ :)
http://www.rbukvar.eu/primer/drobi_tochnost.htm ($2)


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: laskov в May 15, 2010, 09:18
Чисто математически 0.(9) (0 цяло и 9 в период) е 1, освен всичко :)
А след няколко бири даже става 2 :)  [_]3


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: romeo_ninov в May 15, 2010, 11:55
Чисто математически 0.(9) (0 цяло и 9 в период) е 1, освен всичко :)
А след няколко бири даже става 2 :)  [_]3
laskov, ти нали не четеш "Хумор, сатира и забава", защо пишеш като за там?
Марче, 0.9(9) си е 0.9(9), НИКОГА не е 1, ноооо, клони към едно. Което е нещо по-различно :P


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: bop_bop_mara в May 15, 2010, 12:57
Не, точно 1 е.
0.(9)=3*0.(3)=3*(1/3)=1
А понятието клони не е за числа, а за редици и функции.


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: b2l в May 15, 2010, 13:01
Не, точно 1 е.
0.(9)=3*0.(3)=3*(1/3)=1
Не е вярно!


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: bop_bop_mara в May 15, 2010, 13:02
Не, точно 1 е.
0.(9)=3*0.(3)=3*(1/3)=1
Не е вярно!

Е щом считаш, че не е вярно, обясни защо :)


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: romeo_ninov в May 15, 2010, 13:02
Не, точно 1 е.
0.(9)=3*0.(3)=3*(1/3)=1
А понятието клони не е за числа, а за редици и функции.
ДОбре де, имах предвид че с увеличаването на броя на цифрите 0.(9) клони към едно, но не е едно, защото 1-0.(9) !=0 а на безкрайно малко число


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: bop_bop_mara в May 15, 2010, 13:06
Кое от
0.(9)=3*0.(3)=3*(1/3)=1
не е ясно :)
http://en.wikipedia.org/wiki/0.999...


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: romeo_ninov в May 15, 2010, 13:13
Кое от
0.(9)=3*0.(3)=3*(1/3)=1
не е ясно :)
http://en.wikipedia.org/wiki/0.999...
Що ли се намесват редове и клонене към безкрайност? А ти ме оплю за това :P
(http://upload.wikimedia.org/math/6/f/a/6fa510b44742046a167b4b8515162825.png)


Титла: Re: Java и загуба на точност при сумиране на float
Публикувано от: bop_bop_mara в May 15, 2010, 13:18
Не те оплювам, казвам, че думата клони се употребява за редици и функции, думата сходимост е понятие за редици, функции, редове (ама с малко по-друг смисъл) и др. Едно число не клони към друго, едно число е приблизително равно на друго :)
В случая нашето число е представено като граница на числова редица.