Avatar billede keet Nybegynder
19. november 2003 - 18:48 Der er 46 kommentarer og
2 løsninger

metode til beregning af kubikrod

Hvordan laver jeg en metode der kan retunere kubikroden af et givent tal.

Jeg følgende kode:

public static inc cubeRoot(int n) {
  int r;
  while ( ...... ) {
    ....
  }
  return r;
}

Metoden skal returnere et heltal, og der gælder at: r^3 <= n < (r+1)^3
Avatar billede jakoba Nybegynder
19. november 2003 - 19:02 #1
tænk binært.
1  ^3  =  1        //
10 ^3  =  1000    // jo større tal, jo tættere på
11 ^3  = 11011    //      "3 gange så mange binære cifre"
100^3  =  1000000  //
111^3  =101010111

det bruger du ti at få et godt første gæt

(x+1)*(x+1)*(x+1)  =  x^3 +3x^2 +3x + 1

den formel bruger du til at 'justere tallet list' indtil det er korrekt.

mvh JakobA
Avatar billede soreno Praktikant
19. november 2003 - 19:02 #2
Kan du ikke bare gøre sådan:

public class Main
{
    public static int qroot(int n)
    {
        double q_root = Math.pow(n, 0.3333333d);
        return (int)q_root;
    }
   
    public static void main(String[] args)
    {
        for(int i=1;i<=20;i++)
        {
            int temp = i * i * i;
            System.out.println("Kubikroden af " + temp + "\t" + qroot(temp));
        }
    }
}

Output:
Kubikroden af 1    1
Kubikroden af 8    1
Kubikroden af 27    2
Kubikroden af 64    3
Kubikroden af 125    4
Kubikroden af 216    5
Kubikroden af 343    6
Kubikroden af 512    7
Kubikroden af 729    8
Kubikroden af 1000    9
Kubikroden af 1331    10
Kubikroden af 1728    11
Kubikroden af 2197    12
Kubikroden af 2744    13
Kubikroden af 3375    14
Kubikroden af 4096    15
Kubikroden af 4913    16
Kubikroden af 5832    17
Kubikroden af 6859    18
Kubikroden af 8000    19
Avatar billede soreno Praktikant
19. november 2003 - 19:10 #3
Sådan:
    public static int qroot(int n)
    {
        double q_root = Math.pow(n, 0.3333333d);
        return (int)Math.ceil(q_root);
    }
Avatar billede arne_v Ekspert
19. november 2003 - 19:16 #4
Øh.

Du mener:

    public static int qroot(int n) {
        double q_root = Math.pow(n, 1/3.0D);
        return (int) Math.floor(q_root);
    }

ikke ?
Avatar billede keet Nybegynder
19. november 2003 - 19:20 #5
soreno > Metoden virker vist ikke helt korrekt. hvis n=28 retunerer den 4, men det mest korrekte er vel 3. Desuden skal jeg være sikker på at invarianten er overholdt: r^3 <= n < (r+1)^3
Avatar billede soreno Praktikant
19. november 2003 - 19:20 #6
Nej.

Det giver følgende output:
Kubikroden af 1    1
Kubikroden af 8    2
Kubikroden af 27    3
Kubikroden af 64    3
Kubikroden af 125    5
Kubikroden af 216    6
Kubikroden af 343    6
Kubikroden af 512    7
Kubikroden af 729    8
Kubikroden af 1000    9
Kubikroden af 1331    10
Kubikroden af 1728    11
Kubikroden af 2197    12
Kubikroden af 2744    13
Kubikroden af 3375    14
Kubikroden af 4096    15
Kubikroden af 4913    16
Kubikroden af 5832    17
Kubikroden af 6859    18
Kubikroden af 8000    19
Avatar billede arne_v Ekspert
19. november 2003 - 19:21 #7
keet>

Erstat ceil med floor som jeg foreslår, så virker det !
Avatar billede keet Nybegynder
19. november 2003 - 19:22 #8
hov, så ikke ovenstående det virker..
Avatar billede arne_v Ekspert
19. november 2003 - 19:22 #9
søren>

Ceil virker perfekt med alle n^3 værdier !

Problemet er alle værdier midt imellem !
Avatar billede arne_v Ekspert
19. november 2003 - 19:23 #10
Så test med den her i.s.f.:

    public static void main(String[] args) {
        for (int i = 1; i <= 30; i++) {
            int j = qroot(i);
            System.out.println((j*j*j) + " <= " + i + " < " + (j+1)*(j+1)*(j+1));
        }
    }
Avatar billede soreno Praktikant
19. november 2003 - 19:23 #11
ahh, ja.

Nu forstår jeg.
Avatar billede keet Nybegynder
19. november 2003 - 19:26 #12
arne_v > hvis n er 64 retunerer den 3... det er vel 4
Avatar billede jakoba Nybegynder
19. november 2003 - 19:29 #13
kan det være opgaven angler efter en assert

    public static int qroot(int n) {
        double q_root = Math.pow(n, 1/3.0D);
        int 1_q_root = (int) Math.floor(q_root);
        assert  ( Math.pow(i_q_root,3) <= n  && n < Math.pow(i_q_root+1,3) );
        return i_q_root;
    }

mvh JakobA
Avatar billede arne_v Ekspert
19. november 2003 - 19:29 #14
Det har du ret.

God gammeldags FP unøjagtighed.

Måske:

    public static int qroot(int n) {
        double q_root = Math.pow(n, 1/3.0D);
        return (int) Math.floor(q_root + 0.000000001);
    }
Avatar billede keet Nybegynder
19. november 2003 - 19:34 #15
når jeg bruger assert-sætningen er jeg så sikker på at invarianten er overholdt?
Avatar billede keet Nybegynder
19. november 2003 - 19:45 #16
kan problemet egentlig løses med while?
Avatar billede arne_v Ekspert
19. november 2003 - 19:48 #17
Følgende ser faktisk ud til at virke:

    public static int qroot(int n) {
        int guess = n;
        do {
            int newguess = guess - (guess*guess*guess - n) / (3*guess*guess);
            guess = (newguess != guess) ? newguess : newguess - 1;
            if(guess <= 0) guess = 1;
        } while((n < guess*guess*guess) || (n >= (guess+1)*(guess+1)*(guess+1)));
        return guess;
    }
Avatar billede arne_v Ekspert
19. november 2003 - 19:50 #18
Jeg har dog kun checket 1..75
Avatar billede keet Nybegynder
19. november 2003 - 19:51 #19
ok, tak for hjælpen alle... :) Vil I alle svare, for jeg har brugt alles ideer :)
Avatar billede arne_v Ekspert
19. november 2003 - 19:53 #20
svar
Avatar billede jakoba Nybegynder
19. november 2003 - 19:59 #21
Jeg tør ikke garantere at din sidste vil terminere (holde op med at køre rundt i while løkken). Kunne den evt begynde at oscillere?
Avatar billede arne_v Ekspert
19. november 2003 - 20:17 #22
Måske. Men så kunne den forbedres lidt mere.
Avatar billede keet Nybegynder
19. november 2003 - 20:22 #23
hvordan kunne den forbedres?
Avatar billede arne_v Ekspert
19. november 2003 - 20:24 #24
Så man sikrede sig mod at den gik i uendelig løkke.
Avatar billede keet Nybegynder
19. november 2003 - 20:30 #25
er det en nem måde at gøre dette på?
Avatar billede arne_v Ekspert
19. november 2003 - 20:32 #26
Jeg brygger lige på noget.
Avatar billede jakoba Nybegynder
19. november 2003 - 20:36 #27
Det skulle nok gøres med et matematisk bevis.
Avatar billede jakoba Nybegynder
19. november 2003 - 20:44 #28
hvis du kalder
    int kubikrodAf0 = qroot( 0 );

går det galt 2 steder
    division med 0 i første linie i din while
og
    if (guess <= 0) guess = 1;
        // forhindrer at den kan komme til at overholde din invariant
Avatar billede arne_v Ekspert
19. november 2003 - 21:03 #29
public static int qroot(int n) {
        int guess = 1;
        do {
            int newguess = guess - ((guess*guess*guess - n) / (3*guess*guess));
            guess = (newguess != guess) ? newguess : newguess + (Math.random() > 0.5 ? 1 : -1);
            if(guess > 1290) guess = 1290;
            if(guess <= 0) guess = 1;
        } while((n < guess*guess*guess) || (n >= (guess+1)*(guess+1)*(guess+1)));
        return guess;
    }
Avatar billede arne_v Ekspert
19. november 2003 - 21:04 #30
monoton funktion

resulateter boxet 1..1029 hvilket er hvad der kan være i en positiv int

random element til at forhindre at den kører fast

den tror jeg på !
Avatar billede arne_v Ekspert
19. november 2003 - 21:05 #31
Nul og negative tal skal selvfølgelig lige håndteres, men det bør ikke
være noget problem.
Avatar billede arne_v Ekspert
19. november 2003 - 21:07 #32
Jeg har testet med 1 .. 1000000 uden at den hænger
Avatar billede keet Nybegynder
19. november 2003 - 21:11 #33
den behøver ikke at håndtere negative tal...
Avatar billede keet Nybegynder
19. november 2003 - 21:14 #34
Jeg tror jeg klarer mig nu :) Hvad betyder iøvrigt "D" i pow() metoden?
Avatar billede arne_v Ekspert
19. november 2003 - 21:16 #35
Det er bare for at angive double fremfor float.
Avatar billede skurggman Nybegynder
19. november 2003 - 21:39 #36
Hej keet!

Jeg kan næsten forstå på dit spm at du går på datalogi i århus? Hvis det er tilfældet skal du ligge mærke til at du ikke må benytte math klassen, du skal bruge en løkke.

/Kim
Avatar billede keet Nybegynder
19. november 2003 - 22:23 #37
hehe :) ja, dette er jeg klar over :)
Avatar billede skurggman Nybegynder
19. november 2003 - 22:24 #38
Har du så fået den lavet eller skal du have lidt hjælp?
:)
Avatar billede keet Nybegynder
19. november 2003 - 22:29 #39
Jeg har følgende metode:
public static int CubeRoot2(int n)
    {
        int r = n;
        do {
            int a = r - ( (r*r*r - n) / (3*r*r));
            r = (a != r) ? a : a + (Math.random() > 0.5 ? 1 : -1);
            if( r > 1290) r = 1290;
            if(r <= 0) r = 1;
        } while( (n < r*r*r) || (n >= (r+1)*(r+1)*(r+1)) );
        return r;
    }
While-løkken tager ikke højde n=0 men det kan selvfølgelig gøres med en IF og så retunerer 0, ellers ved jeg ikke lige hvordan jeg gør det. Hvad kan jeg erstatte Math-delen med?
Avatar billede keet Nybegynder
19. november 2003 - 22:30 #40
og hvorfor er det at r skal være > 1290... Er den del nødvendig?
Avatar billede arne_v Ekspert
19. november 2003 - 22:35 #41
Hvis r er større end 1290 så vil r*r*r overflow en int og så går der
kuk i beregningen.
Avatar billede arne_v Ekspert
19. november 2003 - 22:36 #42
Hvis du skal forklare logikken, så er det en ganske almindelig
Newtons metode.
Avatar billede keet Nybegynder
19. november 2003 - 22:47 #43
Kan jeg så ikke bare lave r til en Integer?
Avatar billede arne_v Ekspert
19. november 2003 - 22:50 #44
Integer kan ikke klare mere end int.

En long kunne klare mere.

Men hvofor skulle vi ?

Hvis r*r*r overflower en int, så ved vi jo at kubikroden af n er
mindre end r !
Avatar billede jakoba Nybegynder
19. november 2003 - 22:57 #45
men du bør nok ændre udregninging i while betingelsen til at give resultater af type long, for at undgå at (r+1)*(r+1)*(r+1) giver overflow.
Avatar billede arne_v Ekspert
19. november 2003 - 23:10 #46
Det er nok fornuftigt hvis n kan gå op til Integer.MAX_VALUE
Avatar billede keet Nybegynder
19. november 2003 - 23:24 #47
Er det ikke lidt riski at bruge math.random... det er vel ikke lige meget om der bliver lagt 1 til eller trukket 1 fra?
Avatar billede arne_v Ekspert
19. november 2003 - 23:35 #48
Nej - algoritmen bør konvergere og netop muligheden for både +1 og -1 bør
mindske muligheden for at den "hænger fast" et forkert sted.
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





White paper
Tidsbegrænset kampagne: Overvejer du at udskifte eller tilføje printere i din forretning? Vi kan tilbyde én eller flere maskiner gratis