C++ 在c++;在不同的地方使用时,尽管预期相同

C++ 在c++;在不同的地方使用时,尽管预期相同,c++,pow,C++,Pow,我已经展示了两段代码。我不太明白以不同的方式使用pow()如何在这些代码中产生差异。先谢谢你 在这个问题中,你要计算从1到n的所有整数的和,但是你应该取2的所有幂,加上和中的负数 = 4总和等于 - 1. - 2. + 3. - 4. =  - 4,因为1、2和4分别是20、21和22。计算n的t值的答案 #include<bits/stdc++.h> typedef long long ll; typedef double dl; using namespace std;

我已经展示了两段代码。我不太明白以不同的方式使用pow()如何在这些代码中产生差异。先谢谢你

在这个问题中,你要计算从1到n的所有整数的和,但是你应该取2的所有幂,加上和中的负数 = 4总和等于 - 1. - 2. + 3. - 4. =  - 4,因为1、2和4分别是20、21和22。计算n的t值的答案

#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? 
#包括
typedef long-long-ll;
typedef双dl;
使用名称空间std;
int main(){
ll n,t;
lli,cnt=0;
cin>>t;
while(t--)//对于“t”个测试用例
{
cin>>n;

对于(i=1,cnt=0;i显然,给你带来麻烦的值是
n=100000000
,或109。小于或等于该值的2的最大整数幂是229。因此,你试图计算的和是(10^9*(10^9+1))/2-2*(2^30-1),或500000000500-2147483646,或499998352516354

第二种方法之所以有效,是因为二的幂是精确的,并且在减法中使用了整数运算。第一种方法失败,因为表达式是按双精度计算的。第一项,
n*(n+1)/2
,或5000000005000000,是“精确的”,这意味着浮点表示法中没有错误。第二项2147483646也是精确的。本例中的问题发生在减法上。两者之间的差异不精确,这意味着失去了精度

您没有理由使用
pow
。您已经计算了
pow(2,cnt)
。事实上,您根本不需要
cnt
。只需使用

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

for(k=1;k
pow()
操作(并返回)一个浮点数。浮点数本质上是不精确的。请定义“正确”浮点数本质上是不精确的。您只能询问置换错误是否在您可以接受的公差范围内。请查看详细信息。
k
long
类型,而
pow
返回一个
双精度。
您的不一致性源于正在执行的类型之间的转换在第一个例子中,它应该继续使用浮点运算,这(正如已经指出的)是不精确的。在第二个示例中,在对
pow
的初始调用之后,它都是整数算术。在循环
i
之后,它看起来像是
2**cnt
。使用
i
代替
pow(2,cnt)
#include
结合使用名称空间std;
是您可以对自己做的最粗俗的删除愚蠢的事情之一。这有效地将整个标准库拉入全局名称空间,为您命名冲突噩梦做好了准备。