为什么我不能从这个数据集中删除虚假的 0?
Why can't I drop the spurious 0 from this data set?
我在 Visual Studio 中使用 C++ 创建一个 Windows 控制台应用程序,该应用程序将为第一个中存储的 X 的正值计算 X、1/X 和 ln X 的均值n CSV 的 A 列单元格。我的策略是 push_backing 将单元格的内容放入向量中,然后根据向量的条目对值求和(例如 1/X 的倒数)并将结果除以向量长度。 X 的均值略小于应有的值,表明向量长度比样本大小多 1,额外条目为零。这也解释了为什么1/X和-ln X的均值分别是inf和-inf。因此理论上,一种解决方案是在计算统计数据之前 pop_back 向量。不幸的是,我已经尝试了这个和无数其他方法,但没有任何效果。
我将通过复制粘贴代码的最小示例并列出我尝试过的事情来结束。 (如果你认为其中一种方法 "should" 有效,而我可能在执行时出错了,请在发布前检查它,因为这个程序在过去 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 规则以便仅将非零条目添加到数据集;
重命名原始向量 baddataset,然后将数据集定义为第一个 baddataset.size()-1
条目作为 baddataset;
写 int n = dataset.size()-1;
(或其各种语法变体,但似乎没有任何东西传达“小于 1”的指令);
写 int n = dataset.size();
然后使用 n = n-1;或 n--;将 n 减 1;
写 int badn = dataset.size(); int n = badn-1;
(你可以看到我有多绝望);
将求和期间的 for(i = 0; i < n; i++)
替换为 for(i = 0; i < n-1; i++)
,然后在末尾除以 n-1 而不是 n;
声明仅对非零条目进行操作以将某些内容(例如它们的对数)添加到正在计算的总和中;
定义 oldsigma1overxi 等,确保这些 "old" 总和存储其他总和的先前值,并在它们变为 inf 或 nan 时将总和重置为其 "old" 值(这无法解决错误 n 的除法问题,但它是某种东西);
将函数更改为近似值(我最终将处理从 40,000 到 6,000,000,000 的大量数据集),这些数据集在 0 处不发散(我不知道为什么它在我时不计算那样做)。
如评论中所述,问题出在您的 while 循环中:file.good() 仅在 getline() 尝试读取文件末尾失败后才计算为 false。幸运的是,您甚至不需要 file.good(),因为 getline() 的 return 值在文件末尾计算为 false。这使得代码比原来的代码更简单:
while (getline(file, valuetmp))
{
value = ::atof(valuetmp.c_str());
dataset.push_back(value);
}
也就是说,您使用 int n = dataset.size() - 1 的解决方法对我也适用;我不明白为什么它对你不起作用。您也可以在 while 循环之后立即使用 dataset.pop_back() 。当然最好是使用正确的输入密码。
要诊断此类问题,将数据集的内容转储到屏幕或文件中通常是个好主意,可以使用数据的删节版本。这通常可以快速查明问题的本质。
我在 Visual Studio 中使用 C++ 创建一个 Windows 控制台应用程序,该应用程序将为第一个中存储的 X 的正值计算 X、1/X 和 ln X 的均值n CSV 的 A 列单元格。我的策略是 push_backing 将单元格的内容放入向量中,然后根据向量的条目对值求和(例如 1/X 的倒数)并将结果除以向量长度。 X 的均值略小于应有的值,表明向量长度比样本大小多 1,额外条目为零。这也解释了为什么1/X和-ln X的均值分别是inf和-inf。因此理论上,一种解决方案是在计算统计数据之前 pop_back 向量。不幸的是,我已经尝试了这个和无数其他方法,但没有任何效果。
我将通过复制粘贴代码的最小示例并列出我尝试过的事情来结束。 (如果你认为其中一种方法 "should" 有效,而我可能在执行时出错了,请在发布前检查它,因为这个程序在过去 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 规则以便仅将非零条目添加到数据集;
重命名原始向量 baddataset,然后将数据集定义为第一个 baddataset.size()-1
条目作为 baddataset;
写 int n = dataset.size()-1;
(或其各种语法变体,但似乎没有任何东西传达“小于 1”的指令);
写 int n = dataset.size();
然后使用 n = n-1;或 n--;将 n 减 1;
写 int badn = dataset.size(); int n = badn-1;
(你可以看到我有多绝望);
将求和期间的 for(i = 0; i < n; i++)
替换为 for(i = 0; i < n-1; i++)
,然后在末尾除以 n-1 而不是 n;
声明仅对非零条目进行操作以将某些内容(例如它们的对数)添加到正在计算的总和中;
定义 oldsigma1overxi 等,确保这些 "old" 总和存储其他总和的先前值,并在它们变为 inf 或 nan 时将总和重置为其 "old" 值(这无法解决错误 n 的除法问题,但它是某种东西);
将函数更改为近似值(我最终将处理从 40,000 到 6,000,000,000 的大量数据集),这些数据集在 0 处不发散(我不知道为什么它在我时不计算那样做)。
如评论中所述,问题出在您的 while 循环中:file.good() 仅在 getline() 尝试读取文件末尾失败后才计算为 false。幸运的是,您甚至不需要 file.good(),因为 getline() 的 return 值在文件末尾计算为 false。这使得代码比原来的代码更简单:
while (getline(file, valuetmp))
{
value = ::atof(valuetmp.c_str());
dataset.push_back(value);
}
也就是说,您使用 int n = dataset.size() - 1 的解决方法对我也适用;我不明白为什么它对你不起作用。您也可以在 while 循环之后立即使用 dataset.pop_back() 。当然最好是使用正确的输入密码。
要诊断此类问题,将数据集的内容转储到屏幕或文件中通常是个好主意,可以使用数据的删节版本。这通常可以快速查明问题的本质。