On 10/8/07, Matteo Mancini <rsynco / gmail.com> wrote:
> Ho iniziato da poco a programmare in ruby, e stavo facendo un piccolo
> programma che, dato un sistema di disequazioni, trova i punti comuni a
> queste, impostando un problema di programmazione lineare.
> Viene chiesto in input prima il numero di disequazioni (vincoli) e
> quindi i parametri in questo modo:
> ax+by+c>=0
> prima il coefficiente di x, quindi quello di y, il termine noto, e
> infine un quarto parametro da impostare ad 1 o a -1 per il segno della
> disequazione.
> Ho provato il seguente sistema:
> 0.9x+1.5y<=45
> x+y<=36
> x>=10
> y>=0
> Quindi inserisco da input:
> 4 | 0.9 | 1.5 | 45 | -1 | 1 | 1 | 36 | -1 | 1 | 0 | 10 | 1 | 0 | 1 | 0 |
> 1
> I punti in comune calcolati a mano sono:
> (10,0) (36,0) (15,21) (10,24)
> E qui sorge il problema: il programma mi scarta il punto (15,21) alla
> prima disequazione (provate a mano, la verifica!) e la fatidica somma
> 0.9*0.15+1.5*21-45 ridnientepocodimenoche 7.105427357601e-015!!!
> Fatta numericamente d0, eppure il programma sputa fuori questo
> risultato!
> Sono ore che ci combatto, datemi una mano vi prego!
> Grazie in anticipo!
>
>
> Il file principale allegato, seguono le due piccole classi che ho
> implementato:
>
> point.rb
>
> class Point
> attr_reader :x, :y
> def initialize (x,y)
> @x=x
> @y=y
> end
> end
>
> diseq.rb
>
> require 'myrbs\point'
>
> class Diseq < Point
> attr_reader :t,:s
> def initialize (x,y,t,s)
> super(x,y)
> @t=t
> @s=s
> end
> def solve(a,b)
>   c=x*a+y*b-t
>   puts c
>   if(c*s>=0)
>     o=1
>   else
>     o=0
>   end
>   o
> end
> end

Hi,

your problem is that floats are not exact. They have limited
precision, and some numbers (especially irrational and with periodic
fractional part) cannot be stored as floats precisely.
Imagine using decimal notation with max 5 digits: 1/3 = 0.33333 or
0.33334. therefore 3 * 1/3  = 3 * 0.33333 = 0.99999 that is 0.00001
less that expected result. Floats are the same except they use binary
notation and more digits.

One way to avoid it is using BigDecimal instead of floats, although
they are much slower.
Sometimes it's possible to live with the small differences.

Notice that in test/unit, they are checking float results to be within
specified tolerance (assert_in_delta).

(My Italian is sufficient to understand your post, but not to reply ;-)

Jano