复数运算出错
Complex numbers arithmetic goes wrong
现在我正在尝试实现 Poisson binomial distribution 的概率公式。
公式是该部分的最后一个,其中包含复指数:
我有一个非常简单的代码可以执行此操作,但它输出了错误的概率。
#include <iostream>
#include <complex>
#include <cmath>
using namespace std;
int main(int argc, char const *argv[]) {
int N=5; //number of coins
double probabilities[N]={0.1,0.1,0.1,0.1,0.1}; //probabilities of coin landing head
double distr[N+1];
for (int j=0; j<N+1;j++){
complex<double> temp1=0.0 + 0.0i;
for (int k=0; k<N+1;k++){
for(int l=0;l<N+1;l++){
complex<double> temp2=1.0 + 0.0i;
for (int m=0;m<N;m++){
temp2=temp2*(1.0+0.0i+(exp(l*2*M_PI*1.0i/(double(N)+1.0))-1.0+0.0i)*probabilities[m]);
}
temp2=temp2*exp(l*k*2*M_PI*1.0i/(double(N)+1.0));
temp1=temp1+temp2/(double(N)+1.0);
}
}
distr[j]=real(temp1);
}
for (int i=0;i<N+1;i++){
cout<< distr[i] << ' ';
}
这段代码的输出是[1,1,1,1,1,1],肯定是不正确的。我在想,也许我没有正确处理复数,但我看不出我哪里做错了。令人沮丧的是,这样一个简单的程序不起作用:(.
从代码中可以清楚地看出 temp1
不依赖于 j
,因此您得到相同的数字,即 k
的总和。删除 j
上的外循环并写入 distr[k] = real(temp1);
并修复 exp(l*k*...)
中的符号后,您将得到预期的结果:
0.59049 0.32805 0.0729 0.0081 0.00045 1e-05
经过一些简化的完整代码:
int main() {
using namespace std::literals::complex_literals;
constexpr int N = 5;
const double probabilities[N] = {.1, .1, .1, .1, .1};
const auto c = std::exp(2i * M_PI / (N + 1.));
double distr[N + 1];
for (int k = 0; k <= N; ++k) {
auto sum = std::complex<double>(0);
for(int l = 0; l <= N; ++l) {
auto prod = std::complex<double>(1);
for (int m = 0; m < N; ++m)
prod *= 1. + (std::pow(c, l) - 1.) * probabilities[m];
sum += prod * std::pow(c, -l * k) / (N + 1.);
}
distr[k] = std::real(sum);
}
for (auto d : distr)
std::cout << d << ' ';
}
现在我正在尝试实现 Poisson binomial distribution 的概率公式。
公式是该部分的最后一个,其中包含复指数:
我有一个非常简单的代码可以执行此操作,但它输出了错误的概率。
#include <iostream>
#include <complex>
#include <cmath>
using namespace std;
int main(int argc, char const *argv[]) {
int N=5; //number of coins
double probabilities[N]={0.1,0.1,0.1,0.1,0.1}; //probabilities of coin landing head
double distr[N+1];
for (int j=0; j<N+1;j++){
complex<double> temp1=0.0 + 0.0i;
for (int k=0; k<N+1;k++){
for(int l=0;l<N+1;l++){
complex<double> temp2=1.0 + 0.0i;
for (int m=0;m<N;m++){
temp2=temp2*(1.0+0.0i+(exp(l*2*M_PI*1.0i/(double(N)+1.0))-1.0+0.0i)*probabilities[m]);
}
temp2=temp2*exp(l*k*2*M_PI*1.0i/(double(N)+1.0));
temp1=temp1+temp2/(double(N)+1.0);
}
}
distr[j]=real(temp1);
}
for (int i=0;i<N+1;i++){
cout<< distr[i] << ' ';
}
这段代码的输出是[1,1,1,1,1,1],肯定是不正确的。我在想,也许我没有正确处理复数,但我看不出我哪里做错了。令人沮丧的是,这样一个简单的程序不起作用:(.
从代码中可以清楚地看出 temp1
不依赖于 j
,因此您得到相同的数字,即 k
的总和。删除 j
上的外循环并写入 distr[k] = real(temp1);
并修复 exp(l*k*...)
中的符号后,您将得到预期的结果:
0.59049 0.32805 0.0729 0.0081 0.00045 1e-05
经过一些简化的完整代码:
int main() {
using namespace std::literals::complex_literals;
constexpr int N = 5;
const double probabilities[N] = {.1, .1, .1, .1, .1};
const auto c = std::exp(2i * M_PI / (N + 1.));
double distr[N + 1];
for (int k = 0; k <= N; ++k) {
auto sum = std::complex<double>(0);
for(int l = 0; l <= N; ++l) {
auto prod = std::complex<double>(1);
for (int m = 0; m < N; ++m)
prod *= 1. + (std::pow(c, l) - 1.) * probabilities[m];
sum += prod * std::pow(c, -l * k) / (N + 1.);
}
distr[k] = std::real(sum);
}
for (auto d : distr)
std::cout << d << ' ';
}