从对数范围计算每十年的点数
Calculate number of points per decade from logarithmic range
我有一系列以 10 为底的对数间隔点,我需要计算这些点的#points-per-decade。
基于this section from wikipedia我们有#decades = log10(开始/停止)。由此我们应该能够将#points-per-decade 计算为#points / #decades。然而,这并没有给出正确的答案。这是我用来测试此方法的一个简短程序:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <float.h>
class GenLog {
public:
GenLog(double start, double step) : curVal(start), step(step) {
m = 1.0 / step;
b = std::log10(start);
stepi = 0;
};
double operator()() {
++stepi;
double arg = m*stepi+b;
if (arg < DBL_MAX_10_EXP) {
curVal += pow(10.0, arg) - curVal;
} else {
curVal = DBL_MAX;
}
return curVal;
}
private:
double step, stepi, curVal, m, b;
};
int main(int argc, char *argv[])
{
if (argc < 5) {
std::cout << "Wrong number of args: format is [start] [stop] [points-per-decade] [size]\n";
return -1;
}
double start = atof(argv[1]);
double stop = atof(argv[2]);
double ppd = atof(argv[3]);
int size = atoi(argv[4]);
std::vector<double> vals;
vals.push_back(start);
// generate total number of points - 2 (excluding endpoints, GenLog takes in
// starting freq, and #point/dec
std::generate_n(std::back_inserter(vals), size - 2, GenLog(start, ppd));
vals.push_back(stop);
for (auto i : vals) {
std::cout << i << " ";
}
std::cout << "\n---TEST BACKWARDS PPD---\n";
std::cout << "ppd: " << ppd << "\t " << (vals.size()) / std::log10(*std::prev(vals.end()) / vals.front()) << "\n";
return 0;
}
示例输出:
这会生成一个从 1 到 10.1681 的对数间隔点系列,每十年 13 个点,总共 15 个点——尽管原则上你只需要起点和每十年的点来生成系列中的下一个对数点。
如您所见,结果数字(13 和 14.8922)与应有的数字不同。
./so 1.0 10.1681 13 15
1 1.19378 1.4251 1.70125 2.03092 2.42446 2.89427 3.45511 4.12463 4.92388 5.87802 7.01704 8.37678 10 10.1681
---TEST BACKWARDS PPD---
ppd: 13 14.8922
根据我目前的测试,我不认为这是一个差一错误。也许#points-per-decade 的计算在概念上不正确?如果是这样,正确的计算方法是什么?
我计算#points-per-decade 的方法不正确
所以根据 calculations section of the wikipedia article 中的最后一个等式,我们有:
步长 = 10^(1 / #points-per-decade)
因为我们知道步长,我们可以重新安排到
1/#每十年点数 * ln(10)=ln(步长)
最后解决#points-per-decade
#每十年点数 = ln(10) / ln(步长)
我有一系列以 10 为底的对数间隔点,我需要计算这些点的#points-per-decade。
基于this section from wikipedia我们有#decades = log10(开始/停止)。由此我们应该能够将#points-per-decade 计算为#points / #decades。然而,这并没有给出正确的答案。这是我用来测试此方法的一个简短程序:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <float.h>
class GenLog {
public:
GenLog(double start, double step) : curVal(start), step(step) {
m = 1.0 / step;
b = std::log10(start);
stepi = 0;
};
double operator()() {
++stepi;
double arg = m*stepi+b;
if (arg < DBL_MAX_10_EXP) {
curVal += pow(10.0, arg) - curVal;
} else {
curVal = DBL_MAX;
}
return curVal;
}
private:
double step, stepi, curVal, m, b;
};
int main(int argc, char *argv[])
{
if (argc < 5) {
std::cout << "Wrong number of args: format is [start] [stop] [points-per-decade] [size]\n";
return -1;
}
double start = atof(argv[1]);
double stop = atof(argv[2]);
double ppd = atof(argv[3]);
int size = atoi(argv[4]);
std::vector<double> vals;
vals.push_back(start);
// generate total number of points - 2 (excluding endpoints, GenLog takes in
// starting freq, and #point/dec
std::generate_n(std::back_inserter(vals), size - 2, GenLog(start, ppd));
vals.push_back(stop);
for (auto i : vals) {
std::cout << i << " ";
}
std::cout << "\n---TEST BACKWARDS PPD---\n";
std::cout << "ppd: " << ppd << "\t " << (vals.size()) / std::log10(*std::prev(vals.end()) / vals.front()) << "\n";
return 0;
}
示例输出: 这会生成一个从 1 到 10.1681 的对数间隔点系列,每十年 13 个点,总共 15 个点——尽管原则上你只需要起点和每十年的点来生成系列中的下一个对数点。
如您所见,结果数字(13 和 14.8922)与应有的数字不同。
./so 1.0 10.1681 13 15
1 1.19378 1.4251 1.70125 2.03092 2.42446 2.89427 3.45511 4.12463 4.92388 5.87802 7.01704 8.37678 10 10.1681
---TEST BACKWARDS PPD---
ppd: 13 14.8922
根据我目前的测试,我不认为这是一个差一错误。也许#points-per-decade 的计算在概念上不正确?如果是这样,正确的计算方法是什么?
我计算#points-per-decade 的方法不正确
所以根据 calculations section of the wikipedia article 中的最后一个等式,我们有:
步长 = 10^(1 / #points-per-decade)
因为我们知道步长,我们可以重新安排到
1/#每十年点数 * ln(10)=ln(步长)
最后解决#points-per-decade
#每十年点数 = ln(10) / ln(步长)