primtal.xml

Denna kod är public domain. Om ni hittar fel eller vill ändra något i koden blir jag jätteglad om ni skickar dessa ändringar till jesper [at] fantasi [punkt] se.


<?xml version="1.0"?>
<article category="software" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="article.xsd">
  <keyword>Primtal</keyword>
  <topic>Primtal</topic>
  <ingress>
    Att ta reda på om ett tal är ett primtal eller ej är lite
    klurigare än man kan tro. Egentligen handlar det bara om att
    försäkra sig om att talet inte är jämnt delbart med något lägre
    tal vilket i teorin inte är svårt alls. Men om man hanterar
    väldigt stora tal som till exempel nycklar vid kryptering och
    liknande så blir det i praktiken ganska tidsödande att testa alla
    lägre tal.
  </ingress>
  <text>
    Eratosthenes såll är en naiv algoritm som utvecklades av den gamla
    greken Eratosthenes runt år -200. Algoritmen tar en övre gräns och
    sållar bort allt som inte är primtal under gränsen. Efteråt finns
    bara primtalen kvar. Själva sållningen går till så att man börjar
    från 2 och plockar bort alla tal under gränsen som är delbara med
    2. Sen tar man 3, plockar bort alla tal delbara med 3, fortsätt
    med 4 ... osv upp till gränsen. På <a href="source.php">kodsidan</a>
    finns algoritmen implementerad i flera olika programmeringsspråk.
  </text>
  <text>
    Om man nu bara är intresserad av att testa om ett enda tal
    (<code>x</code>) är ett primtal så kan man använda en förenklad
    version av Eratosthenes såll. Det räcker då att kolla
    att <code>x</code> inte är jämnt delbart med något tal
    under <code>x</code> med en loop som den nedan.
  </text>
  <codebox>
  bool testForPrime(int x)
  {
     for (int i = 2; i <lt/> x; i++) {
        if (x % i == 0) {
           // Inte primtal.
           return false;
        }
     }
     // Primtal!!
     return true;
  }
  </codebox>
  <text>
    Det är ganska lätt att förbättra prestandan i Eratosthenes såll
    genom att utnyttja det vi vet om primtal och delbarhet. Till
    exempel vet vi att inga jämna tal förutom två kan vara primtal, så
    givet att <code>x!=2</code> måste LSB vara ett för att det ens ska
    vara värt att testa något. Givet det vet vi också
    att <code>x</code> inte kan vara jämnt delbart med något tal
    större än <code>x/3</code>. Vi får då ett lite effektivare test.
  </text>
  <codebox>
  bool testForPrime(int x)
  {
     int upperLimit;

     // Inga jämna tal förutom två kan vara primtal
     if (x == 2)
        return true;
     else if (x <amp/> 1 == 0)
        return false;

     // Testa endast udda tal upp till x/3
     upperLimit = x / 3;
     for (int i = 3; i <lt/>= upperLimit; i += 2) {
        if (x % i == 0) {
           // Inte primtal.
           return false;
        }
     }
     // Primtal!!
     return true;
  }
  </codebox>

  <subtopic>Stora primtal</subtopic>
  <text>
    Om det nu är kryptologi man är ute efter och vill testa riktigt
    stora tal (tal med 30-40 siffror) så är dessa metoder inte
    praktiska eftersom de tar för lång tid. En populär metod som ofta
    används för generering av nycklar vid till exempel RSA-kryptering
    är witness.
  </text>
  <text>
    Witness är en algoritm som kontrollerar om ett tal <em>inte
    kan</em> vara ett primtal. Om algoritmen svarar sant är talet
    garanterat inte ett primtal, om resultatet är falskt kan det vara
    ett primtal. Sannorlikheten för att witness ska svara fel är
    mindre än 0,5. Detta innebär att om algoritmen anropas ett antal
    gånger i rad och den svarar falskt varje gång så kan man till slut
    vara ganska säker på att det är ett primtal. Det är naturligtvis
    en slump inblandad här, annars skulle ju svaret alltid vara det
    samma.
  </text>
  <text>
    Algoritmen finns implementerad
    på <a href="source.php">kodsidan</a>. Den anropas med två
    tal, <code>slump</code> och <code>prima</code>. <code>prima</code>
    är talet vi vill testa om det kan vara ett primtal
    och <code>slump</code> är ett slumptal som är lägre
    än <code>prima</code>. Eftersom <code>slump</code> ska vara lägre
    än <code>prima</code> och det inte fungerar så bra med 0 och 1 så
    funkar denna implementation av algoritmen inte jättebra på de
    lägsta talen (1 kommer till exempel att klassas som "inte
    primtal"). Men eftersom vi är ute efter riktigt stora tal här så
    kanske det inte gör så mycket.
  </text>
</article>