Condizioni al contorno per il test

4

Ok così in un test di programmazione mi è stata data la seguente domanda.

Question 1 (1 mark)

Spot the potential bug in this section of code:

void Class::Update( float dt )
{
    totalTime += dt;
    if( totalTime == 3.0f )
    {
        // Do state change
        m_State++;
    }
}

Le risposte a scelta multipla per questa domanda erano.

a) It has a constant floating point number where it should have a named constant variable

b) It may not change state with only an equality test

c) You don't know what state you are changing to

d) The class is named poorly

Ho risposto erroneamente a questo con la risposta C.

Alla fine ho ricevuto un feedback sulle risposte e il feedback per questa domanda era

Correct answer is a. This is about understanding correct boundary conditions for tests. The other answers are arguably valid points, but do not indicate a potential bug in the code.

La mia domanda qui è, che cosa ha a che fare con le condizioni al contorno? La mia comprensione delle condizioni al contorno sta verificando che un valore rientri in un determinato intervallo, il che non è il caso in questo caso. Osservando la domanda, a mio parere, B dovrebbe essere la risposta corretta quando si considerano i problemi di accuratezza dell'utilizzo di valori in virgola mobile.

    
posta ctor 28.08.2012 - 23:38
fonte

5 risposte

14

Penso che la domanda del test sia ambigua e vaga.

Il problema, ovviamente, è che stai confrontando un numero in virgola mobile con qualcosa (il tipo di ciò che viene confrontato non è specificato), mentre il confronto all'interno di un dato intervallo (un epsilon) è più appropriato, perché confrontare i numeri in virgola mobile con == non è affidabile.

Se il numero in virgola mobile viene confrontato con una "costante denominata" o meno è un dettaglio irrilevante.

Un altro esempio di scelta di come le domande di test create dagli accademici senza esperienza sul campo in genere fanno schifo.

    
risposta data 28.08.2012 - 23:47
fonte
4

Penso che il vero bug nel codice risieda nel fatto che esiste la possibilità che il codice aggiunga l'input insieme e si aspetti che raggiunga un determinato valore. Questo potrebbe non succedere mai.

Considera questo caso:

Update(0.1f);
Update(1.1f);
Update(0.2f);
Update(1.8f);

Dopo l'ultima chiamata all'aggiornamento, la variabile TotalTime interna ha il valore di (0.1 + 1.1 + 0.2 + 1.8) 3.2f (ignorando eventuali errori in virgola mobile). Come tale, il test per TotalTime == 3.0f fallirà da quel punto in poi, nulla potrà mai risolvere quel problema durante la vita del programma (eccetto il potenziale wrap-around variabile).

Questo problema non ha nulla a che fare con l'input essendo in virgola mobile (sebbene sia anche un problema valido in questo caso), comunque. Un problema simile può sorgere anche se l'input fosse costituito da numeri interi. Considera il caso in cui Update() prende la variabile dt come millisecondi e come tale è integer. Cosa accadrebbe se il confronto fosse qualcosa come if(TotalTime == 3000) { (per verificare se TotalTime è cumulabile a 3000 millisecondi). Cosa succede se l'input della funzione non si accumula mai esattamente a 3000? Cosa succede se è esattamente 2999 ad un certo punto, e quindi la funzione viene chiamata con il valore di 2? La variabile TotalTime cresce da 2999 a 3001, e come tale non raggiunge mai 3000, e come tale il test fallisce.

Per risolvere questo problema, il test dovrebbe utilizzare >= operator invece che asserisce che "TotalTime è 3.0f o più". In tal caso non si verificherà alcun errore indipendentemente dall'input alla funzione.

Pertanto, non credo che le risposte fornite siano sufficienti.

    
risposta data 29.08.2012 - 00:16
fonte
3

La risposta corretta dovrebbe essere b . Tutti gli altri punti sono in qualche modo validi 1 , ma confrontare i valori in virgola mobile per l'uguaglianza è qualcosa che dovrebbe essere fatto con molta cura.

Ad esempio, l'aggiunta di dieci% di0.2 s e dieci% di0.1 s rende un 3 diverso da 3.0 (link a Ideone ).

L'uso di "numeri magici" e l'uso di nomi di classe non descrittivi sono anch'essi cose sbagliate, ma non sono errori. Confrontare una costante a virgola mobile per l'uguaglianza, d'altra parte, è quasi certamente un errore.

1 Tranne c : è una classica risposta "assurda".     
risposta data 29.08.2012 - 00:09
fonte
1

3.0 è il limite. che incrementa m_State quando viene raggiunto.

Il punto è che 3.0f è hard coded. L'autore della domanda pensa che avrebbe dovuto essere una variabile costante denominata.

My question here is, what does this have to do with boundary conditions? My understanding of boundary conditions is checking that a value is within a certain range, which isn't the case here

Quindi sì, che è il caso qui.

    
risposta data 28.08.2012 - 23:53
fonte
1

Tutto su questa domanda indica che l'insegnante non è molto bravo nel suo lavoro.

  • cattiva lingua / grammatica: le prime 2 risposte si riferisce al programma così come, nella 3a risposta, il programma ti chiama. Per essere più coerente e avere uno stile migliore avrebbe dovuto essere almeno: "Non sai a quale stato si sta cambiando."
  • nella prima risposta il "numero a virgola mobile costante" è confuso e dovrebbe essere "float letterale", che è più preciso ed è molto più comunemente usato per descrivere .. un letterale:)
  • nell'esempio una variabile è chiamata "m_State" dove la convenzione è che il prefisso "m_" indica che la variabile è una variabile membro. Ma allora cos'è il TotalTime, non è definito nella funzione, quindi probabilmente è anche una variabile membro e apparentemente non segue la convenzione. Forse è globale, ma quando viene usato il prefisso "m_", il prefisso "g_" viene anche usato di solito per indicare una variabile globale. Potrebbe essere una variabile definita solo in quell'unità di traduzione (ad esempio nel file .cpp in cui è definita questa funzione), ma questo è solo uno stile sbagliato. Quindi sì, cosa succede con questa variabile ..
  • ogni risposta è corretta:
    • a) Che cosa rappresenta il valore letterale 3.0f, è davvero un cattivo stile scrivere un codice del genere. Il lettore del codice non ha idea del perché 3.0 sia una 'condizione limite'. Tuttavia non infrange il codice.
    • b) Quando confronti i float per l'uguaglianza, un modo migliore per farlo è: %codice% E anche questo è disapprovato in alcune cerchie, usano un bool floats_are_equal(float a, float b) { return std::abs(a - b) < std::numeric_limits<float>::epsilon() } per convertire la rappresentazione bit del float in un int (senza segno) (con la stessa rappresentazione di bit in memoria) e quindi puoi fare un confronto esatto. Anche questo è chiaramente la cosa più sbagliata con questo pezzo di codice, perché questo probabilmente farà sì che il codice semplicemente non faccia ciò che è destinato a fare. Tutte le altre risposte hanno più a che fare con lo stile.
    • c) Non sai in quale stato si sta passando il programma, è corretto. Ti dice che probabilmente è il prossimo stato, questo potrebbe essere sufficiente a seconda del contesto. Direi che questa risposta sia la meno corretta;)
    • d) una classe chiamata Class è in effetti chiamata molto poco, ovviamente. E penso che sia peggio che usare un letterale. Anche se si tratta dello stesso livello.

In conclusione, questa domanda non fornisce alcuna informazione utile sulla persona che sta effettuando il test. In generale le domande a scelta multipla non sono un buon modo per verificare se qualcuno capisce qualcosa. Va bene se devi memorizzare i fatti. Ma in questo caso una risposta gratuita sarebbe stata molto meglio.

    
risposta data 05.09.2014 - 21:07
fonte

Leggi altre domande sui tag