Avatar billede nf_maz Nybegynder
05. november 2002 - 10:12 Der er 5 kommentarer og
2 løsninger

float -> brøk

Hvordan konverterer man en float (eller double for den sags skyld) til en brøk?

F.eks. 0.3333333 til 1/3 eller 0.1 til 1/10

Kan man gøre det uden at bruge en løkke som afprøver en masse talkombinationer?
Avatar billede carstenknudsen Nybegynder
05. november 2002 - 10:27 #1
Der findes ingen metoder i standard API'en
der gør det. Der er dog algoritmer til at
approksimere flydende tal med brøker.
Avatar billede nf_maz Nybegynder
05. november 2002 - 11:04 #2
mja, jeg tænkte det nok... jeg ville helst undgå at skrive algoritmen selv, kender du et sted man kan finde en der er skrevet...?
Avatar billede carstenknudsen Nybegynder
05. november 2002 - 12:08 #3
Her er en meget simpel og primitiv klasse
jeg lige har skrevet der forsøger at
approksimere en double som en brøk.
Du skal kalde metoden getFraction med
tallet der skal approksimeres og
præcisionen af approksimationen.
Det er en meget ineffektiv beregnings-
metode der let kunne optimeres, men det
har jeg ikke tid til lige nu.
public class Fraction {
    private int num, denom;
    public Fraction( int num, int denom ) {
    this.num = num;
    this.denom = denom;
    }
    public int getNumerator() {
    return num;
    }
    public int getDenominator() {
    return denom;
    }
    public static Fraction getFraction( double x, double eps ) {
    if ( x < 0 ) throw new RuntimeException( "Number is negative." );
    int max = (int) (1/eps+0.5);
    for (int i = 1; i <= max; i++) {
        for (int j = 1; j <= max; j++) {
        double frac = ((double) i) / j;
        if ( Math.abs( frac - x ) < eps )
            return new Fraction(i,j);
        }
    }
    throw new RuntimeException( "Number could not be approximated." );
    }
    public String toString() {
    return num + "/" + denom;
    }
    public static void main( String[] args ) {
    Fraction f = Fraction.getFraction( 4+1.0/3.0+1.0/10.0, 0.000543 );
    System.out.println( f );
    }
}
Avatar billede nf_maz Nybegynder
05. november 2002 - 13:25 #4
carsten> fornemt! det virker fint, men jeg skal lige have styr på syntaksen... Det skulle gerne være sådan at man bare kaldte getFraction med en float variabel som argument (f.eks. Fraction.getFraction(0.3333333333), og den så returnerer en brøk - jeg kan ikke lige gennemskue hvad "4+1.0/3.0+1.0/10.0, 0.000543" dækker over...?
Avatar billede carstenknudsen Nybegynder
05. november 2002 - 13:34 #5
Det første argument er det tal du vil
lave til en brøk. Det andet argument
angiver hvilken præcision du kræver dvs.
hvad må forskellen på brøken og tallet være.
0.33333 er ikke 1/3, ej heller er 0.3333333333
lig 1/3, men 1/3 er en god approksimation
(i nogle tilfælde). Hvis du beregner 1.0/3.0
får du ikke brøken 1/3 så derfor skal du angive
en præcision.
Avatar billede arne_v Ekspert
05. november 2002 - 23:59 #6
En modificeret version:

public class Fraction {
    private final static double EPS = 0.0000001;
    private int a;
    private int b;
    private Fraction(int a, int b) {
        this.a = a;
        this.b = b;
    }
    public static Fraction calc(double x) {
        int a2 = 1;
        int b2 = 2;
        double x2;
        for(;;) {
          x2 = (double)a2/(double)b2;
          if((Math.abs(x2-x) / x) < EPS) break;
          if(x2>x) {
              b2++;
          } else {
              a2++;
          }
        }
        return new Fraction(a2, b2);
    }
    public String toString() {
        return (a + "/" + b);
    }
}

Ændringer:
* ikke 2 simple for løkker men en mere direkte
  vej mod svaret, som jeg er ret sikker på er hurtigere
* et relativt test i.s.f. et absolut test, som jeg
  mener er bedre i tilfælde af meget små brøker
Avatar billede nf_maz Nybegynder
14. november 2002 - 20:42 #7
Tak for hjælpen! Arne fik lidt mere for at lave en noget mere brugervenlig metode, men tak til jer begge
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester