2015-11-13 3 views
2

J'ai montré deux morceaux de code. Je ne comprends pas très bien comment utiliser pow() modifie différemment ces codes. Merci beaucoup d'avance.réponses différentes en utilisant pow() en C++ lorsqu'il est utilisé à différents endroits, bien que le même est prévu

Dans ce problème, vous devez calculer la somme de tous les entiers de 1 à n, mais vous devez prendre toutes les puissances de deux avec moins dans la somme.Par exemple, pour n = 4, la somme est égale à - 1 - 2 + 3 - 4 = - 4, car 1, 2 et 4 sont 2 , 2 et 2 respectivement. Calculez la réponse pour t valeurs de n.

#include<bits/stdc++.h>  
typedef long long ll; 
typedef double dl; 
using namespace std; 
int main() { 
    ll n,t; 

    ll i,cnt=0; 
    cin>>t; 
    while(t--)// for 't' number of test cases 
    { 
     cin>>n; 

      for(i=1,cnt=0;i<=n;i*=2,cnt++); //counting number of terms in the GP:1,2,4,.... 
      cout<<setprecision(20)<<((n*(n+1))/2)-(2*(pow(2,cnt)-1))<<endl; 
    } 
    return 0; 

} 
//output for above code:499999998352516352 
// and the slightly modified code.. 


#include<bits/stdc++.h> 
typedef long long ll; 
typedef double dl; 
using namespace std; 
int main() { 
    ll n,t; 

    ll i,cnt=0; 
    cin>>t; 
    while(t--)// for 't' number of test cases 
    { 
    cin>>n; 

    for(i=1,cnt=0;i<=n;i*=2,cnt++); 
    ll k=(pow(2,cnt)); //instead of directly printing the answer, 'k' is computed and then used to find the answer. 
    cout<<setprecision(20)<<((n*(n+1))/2)-(2*(k-1))<<endl; 
    } 
    return 0; 

} 
//output for above code:499999998352516354 
// the second one is the correct answer, the first one is wrong. how does pow() change the values here? 
+5

'pow()' fonctionne (et renvoie) un nombre à virgule flottante. Les nombres à virgule flottante sont intrinsèquement inexacts. –

+0

Merci, mais alors comment savons-nous quel usage fonctionnerait correctement? – Sreenidhi

+5

Définir "correctement". Les nombres à virgule flottante sont, dans leur essence même, inexacts. Vous pouvez seulement demander si l'erreur de copulation est dans une tolérance acceptable pour vous. Jetez un coup d'œil à [ce que tout informaticien devrait savoir sur l'arithmétique en virgule flottante] (http://floating-point-gui.de/) pour plus de détails. – Angew

Répondre

2

Apparemment, la valeur de qui vous donne du mal est n=1000000000, ou 10 . La plus grande puissance intégrale de 2 inférieure ou égale à cette valeur est 2 . La somme que vous essayez de calculer est donc (10^9 * (10^9 + 1))/2-2 * (2^30-1), ou 500000000500000000-2147483646, ou 499999998352516354.

Votre deuxième approche fonctionne parce que les puissances de deux sont exactes et parce que vous utilisez l'arithmétique entière dans votre soustraction. Votre première approche échoue parce que l'expression est calculée comme un double. Le premier terme, n*(n+1)/2, ou 500000000500000000, est "exact", ce qui signifie qu'il n'y a pas d'erreur dans la représentation en virgule flottante. Le deuxième terme, 2147483646, est également exact. Le problème dans ce cas se produit avec la soustraction. La différence entre les deux est inexacte, ce qui signifie que vous avez perdu la précision.

Vous n'aviez aucune raison d'utiliser pow. Vous avez déjà calculé pow(2,cnt). En fait, vous n'avez pas du tout besoin de cnt. Il suffit d'utiliser

ll k; 
for(k=1; k<=n; k*=2);