Elaborazione
Output
TMemo


L'applicazione che si sta costruendo deve produrre un output abbastanza complesso: una sequenza di potenze di numeri primi. Per preparare un supporto adatto a questo output si può usare il componente TMemo disponibile nella palette di C++Builder.

TMemo è pressapoco un semplice editor, come Notepad, in cui è possibile scrivere righe di testo una di seguito all'altra. La sua proprietà più significativa è Lines in cui vengono memorizzate le righe di testo. Ma è l'applicazione che produce queste righe: l'utente non deve scrivere testo e quindi alla proprietà ReadOnly viene dato valore true.

TMemo deve occupare tutto lo spazio rimasto disponibile nella TForm: alla proprietà Align viene dato valore alClient.

Se il testo prodotto è molto e supera le dimensioni della TForm l'utente, per vedere tutto l'output, deve poter far scorrere verticalmente il contenuto di TMemo: la proprietà ScrollBars deve aver valore ssVertical.

Cliccare sull'icona di TMemo e poi sulla TForm e passare nello Object Inspector ad assegnare le proprietà del componente introdotto.

Salvare il codice prodotto, compilare e lanciare. Dovrebbe apparire questa schermata.

figura 2

Rimane ora da mettere a punto la parte più importante dell'applicazione, cioè la produzione della scomposizione del numero registrato in numero.

Questa operazione viene associata alla voce MnScomposizione del menù. Selezionare questo item in Object Inspector, accanto all'evento OnClik scrivere CmdScomposizione e premere Invio. Si passa nell'ambiente di editing dove appare l'intestazione del metodo:

void __fastcall TFrmScomposizione::CmdScomposizione(TObject *Sender)
{

}

Per compilare il corpo del metodo, per prima cosa si cancella tutto quanto può essere stato scritto in foglio, il TMemo introdotto per l'output.

void __fastcall TFrmScomposizione::CmdScomposizione(TObject *Sender)
{
foglio->Lines->Clear();
}

numero è una proprietà della classe: è quindi permanente e accessibile ai suoi metodi. La prima riga da aggiungere a foglio (appena ripulito) può essere il messaggio "Scomposizione del numero " completato dal numero dato.

void __fastcall TFrmScomposizione::CmdScomposizione(TObject *Sender)
{
  foglio->Lines->Clear();
foglio->Lines->Add("Scomposizione di "+ IntToStr(numero));
}

Se il numero è minore di 4 non c'è molto da fare: la sua scomposizione coincide con il numero stesso. Si scrive il numero in foglio, si rende visibile foglio e si chiude l'elaborazione.

void __fastcall TFrmScomposizione::CmdScomposizione(TObject *Sender)
{
  foglio->Lines->Clear();
  foglio->Lines->Add("Scomposizione di "+ IntToStr(numero));
if (numero<4)
    {
      foglio->Lines->Add(IntToStr(numero));
      foglio->Show();
      return;
    }
}

Per numeri più grandi si può procedere così.

Se il numero è pari lo si divide per 2 e se si ottiene un quoziente pari si divide il quoziente per 2 fino a che non si ottiene un quoziente dispari. Il numero di divisioni fatte, se è maggiore di 0, sarà l'esponente da dare a 2 nella scomposizione in fattori.

Per controllare se un numero è pari, dato che i numeri sono codificati in bit, è sufficiente controllare se il bit più basso è 0. A questo scopo si può usare l'operatore and aritmetico tra il numero da controllare e 1. Il segno da usare per indicare and aritmetico è &.

Per dividere un numero per 2, basta far slittare tutti i suoi bit verso destra. L'operatore di slittamento a destra (right shift) è >>.

Per indicare che un numero n deve slittare verso destra di 1 posto e che il nuovo valore di n deve diventare quello slittato si scrive così.

n >>= 1;

Poiché la sequenza di divisioni per due deve continuare fintanto che il dividendo è pari, per comandare la ripetizione delle divisioni si usa il ciclo while.

void __fastcall TFrmScomposizione::CmdScomposizione(TObject *Sender)
{
  foglio->Lines->Clear();
  foglio->Lines->Add("Scomposizione di "+ IntToStr(numero));
  if (numero<4)
    {
      foglio->Lines->Add(IntToStr(numero));
      foglio->Show();
      return;
    }
unsigned long esponente=0, dividendo = numero;
  while ((dividendo & 1)==0) //fintanto che dividendo è pari
    {
      dividendo >>= 1;       //dividerlo per due
      esponente++;           //e aumentare l'esponente di una unità
    }
  if (esponente)             //se l'esponente ottenuto è maggiore di 0
                             //scrivere la potenza di 2
                             //e azzerare l'esponente
    {
      foglio->Lines->Add("2^"+IntToStr(esponente));
      esponente = 0;
    }
}

Se al termine del ciclo di divisioni per 2 è rimasto come numero da scomporre 1, l'elaborazione è finita. In caso contrario si controllerà la divisibilità per i successivi numeri dispari (il cui valore è assegnato a base) fino a che non si oltrepassi la radice quadrata del numero dato.

Per controllare se un numero m è divisibile per un numero n si guarda se il resto della divisione (tra interi) è zero. Il resto è dato dall'operatore %.

Se il resto è nullo, si incrementa l'esponente e si torna a dividere il quoziente.

Se il resto non è nullo si passa al numero dispari successivo e si azzera l'esponente.

Si cicla fintanto che la base non supera la radice quadrata e non si ottiene quoziente 1.

void __fastcall TFrmScomposizione::CmdScomposizione(TObject *Sender)
{
  foglio->Lines->Clear();
  foglio->Lines->Add("Scomposizione di "+ IntToStr(numero));
  if (numero<4)
    {
      foglio->Lines->Add(IntToStr(numero));
      foglio->Show();
      return;
    }
  unsigned long esponente=0, dividendo = numero;
  while ((dividendo & 1)==0)
    {
      dividendo >>= 1;
      esponente++;
    }
  if (esponente)
    {
      foglio->Lines->Add("2^"+IntToStr(esponente));
      esponente = 0;
    }
if (dividendo>1)
    {
      double radiceq = sqrt(numero);
      unsigned long base = 3;

      while ((dividendo>1) && (base <= radiceq))
        if ((dividendo % base)==0)
          {
            dividendo /= base;
            esponente++;
          }
        else
          {
            if (esponente)
              {
                foglio->Lines->Add(IntToStr(base)+'^'+IntToStr(esponente));
                esponente = 0;
              }
            base += 2;
          }
      if (esponente)
        foglio->Lines->Add(IntToStr(base)+'^'+IntToStr(esponente));
      else
        foglio->Lines->Add(IntToStr(dividendo)+"^1");
    }
  foglio->Show();
}

Salvare, compilare e lanciare per controllare se tutto funziona a dovere.

Provare ad arricchire le prestazioni dell'applicazione facendo in modo che venga dichiarato se il numero elaborato è primo o no.


prontuario

scomposizione1

Valid XHTML 1.0