Проблем с прецизността на математическите операции на Ruby

Знаете ли как да коригирате следния проблем с математическа точност?

p RUBY_VERSION # => "1.9.1"
p 0.1%1 # => 0.1
p 1.1%1 # => 0.1
p 90.0%1 # => 0.0
p 90.1%1 # => 0.0999999999999943
p 900.1%1 # => 0.100000000000023

p RUBY_VERSION # => "1.9.2"
p 0.1%1 # => 0.1
p 1.1%1 # => 0.10000000000000009
p 90.0%1 # => 0.0
p 90.1%1 # => 0.09999999999999432
p 900.1%1 # => 0.10000000000002274

person Andrei    schedule 23.09.2010    source източник
comment
Това е зададено 4000 пъти предполагам.   -  person Alexandre C.    schedule 23.09.2010
comment
възможен дубликат на Прецизност на плаваща запетая   -  person duffymo    schedule 23.09.2010


Отговори (3)


Голям десетичен знак


Както каза човекът;

Свиването на безкрайно много реални числа в краен брой битове изисква приблизително представяне.


Въпреки това постигнах голям успех с помощта на BigDecimal клас. Да цитирам интрото му

Ruby предоставя вградена поддръжка за целочислена аритметика с произволна точност. Например:

42**13 -> 1265437718438866624512

BigDecimal предоставя подобна поддръжка за много големи или много точни числа с плаваща запетая.


Вземам един от вашите примери;

>> x = BigDecimal.new('900.1')
=> #<BigDecimal:101113be8,'0.9001E3',8(8)>
>> x % 1
=> #<BigDecimal:10110b498,'0.1E0',4(16)>
>> y = x % 1
=> #<BigDecimal:101104760,'0.1E0',4(16)>
>> y.to_s
=> "0.1E0"
>> y.to_f
=> 0.1


Както можете да видите, осигуряването на прилична прецизност е възможно, но изисква малко усилия.

person Chris McCauley    schedule 23.09.2010
comment
Ум! Вие не просто добавяте точност: вие избирате по-добро представяне на десетичните числа. 1/3 пак ще бъде закръглена. - person xtofl; 23.09.2010
comment
@xtofl - това е справедливо мнение, но се надявах, че цитатът за „приблизително представяне“ го засяга. - person Chris McCauley; 23.09.2010

Това важи за всички компютърни езици, не само за Ruby. Това е функция за представяне на числа с плаваща запетая на двоични компютри:

Какво всеки компютърен специалист трябва да знае за аритметиката с плаваща запетая

person duffymo    schedule 23.09.2010

Записването на 0.1 с плаваща запетая винаги ще доведе до грешки при закръгляване. Ако искате „прецизно“ десетично представяне, трябва да използвате Decimal тип.

person xtofl    schedule 23.09.2010
comment
Не съм забелязал такъв проблем в PHP. Има ли някаква основателна причина Ruby да няма "точно" десетично представяне по подразбиране? - person Andrei; 23.09.2010
comment
PHP има същия проблем, защото не става дума за език: php.net/manual/ en/language.types.float.php - person duffymo; 23.09.2010