我在 Visual Studio 中使用 C++ 创建一个 Windows 控制台应用程序,该应用程序将针对存储在 CSV。我的策略是将单元格的内容 push_backing 到一个 vector 中,然后根据 vector 的条目对值求和(例如 1/X 的倒数)并将结果除以 vector 长度。 X 的均值略小于应有的值,表明 vector 长度比样本大小多 1,额外条目为零。这也解释了为什么1/X和-ln X的均值分别是inf和-inf。所以理论上,一种解决方案是在计算统计数据之前 pop_back vector 。不幸的是,我已经尝试过这种方法和无数其他方法,但没有任何效果。
最后,我将复制粘贴代码的最小示例,并列出我尝试过的内容。 (如果您认为其中一种方法“应该”起作用,而我可能在执行时出错了,请在发布前检查它,因为这个程序在过去 3 天里出奇地顽固。)我使用的 CSV 是 here .
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <numeric>
#include <stdio.h>
#include <math.h>
#include <vector>
int main()
{
std::ifstream file("Example.csv");
double value;
std::string valuetmp;
std::vector<double> dataset;
dataset.clear();
while (file.good())
{
getline(file, valuetmp);
value = ::atof(valuetmp.c_str());
dataset.push_back(value);
}
int n = dataset.size();
int i;
double sigmaxi;
sigmaxi = 0;
for (i = 0; i < n; i++) {
sigmaxi += dataset[i];
}
double meanxi;
meanxi = sigmaxi / (1.0*n);
double sigma1overxi;
sigma1overxi = 0;
for (i = 0; i < n; i++) {
sigma1overxi += 1.0 / dataset[i];
}
double mean1overxi;
mean1overxi = sigma1overxi / (1.0*n);
double sigmalnxi;
sigmalnxi = 0;
for (i = 0; i < n; i++) {
sigmalnxi += log(dataset[i]);
}
double meanlnxi;
meanlnxi = sigmalnxi / (1.0*n);
std::cout << "The mean of X is ";
std::cout << meanxi << ", whereas the mean of 1/X is ";
std::cout << mean1overxi << ", and the mean of ln X is ";
std::cout << meanlnxi << ". \n";
std::cout << "Press ENTER to close.";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return 0;
}
我试过:
删除-删除习语;
更改 push_back 规则,以便仅将非零条目添加到数据集;
重命名原始 vector baddataset,然后将dataset定义为第一个baddataset.size()-1
作为坏数据集的条目;
写入整数 n = dataset.size()-1;
(或其各种句法变体,但似乎没有任何东西传达“比那个少 1”的指令);
写入整数 n = dataset.size();
然后使用 n = n-1;或 n--;将 n 减 1;
写入整数 badn = dataset.size(); int n = badn-1;
(你可以看到我有多绝望);
替换 for(i = 0; i < n; i++)
在求和期间 for(i = 0; i < n-1; i++)
, 然后在最后除以 n-1 而不是 n;
声明只有非零条目被操纵以将某些东西(例如它们的对数)添加到正在计算的总和中;
定义 oldsigma1overxi 等,确保这些“旧”和存储其他和的先前值,并在它们变为 inf 或 nan 时将和重置为它们的“旧”值(这不能修复除法- 错误的 n 问题,但它会是什么);
将函数更改为近似值(我最终将处理从 40,000 到 6,000,000,000 的大量数据集),这些数据在 0 处不发散(我不知道为什么在我这样做时它不计算).
最佳答案
如评论中所述,问题出在您的 while 循环中:file.good() 仅在 getline() 尝试读取文件末尾失败后才计算为 false。幸运的是,您甚至不需要 file.good(),因为 getline() 的返回值在文件末尾评估为 false。这使得代码比原来的代码更简单:
while (getline(file, valuetmp))
{
value = ::atof(valuetmp.c_str());
dataset.push_back(value);
}
也就是说,您使用 int n = dataset.size() - 1 的解决方法对我也适用;我不明白为什么它不适合你。您也可以在 while 循环之后立即使用 dataset.pop_back() 。最好当然是使用正确的输入代码。
要诊断此类问题,通常最好将数据集的内容转储到屏幕或文件中,可以使用数据的删节版本。这通常可以快速查明问题的性质。
关于c++ - 为什么我不能从这个数据集中删除虚假的 0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35113201/