将它们添加到 C++ 中 JsonCpp 模块中的数组后的错误值
Posted
技术标签:
【中文标题】将它们添加到 C++ 中 JsonCpp 模块中的数组后的错误值【英文标题】:Bad values after adding them to array in JsonCpp module in C++ 【发布时间】:2017-06-02 17:46:16 【问题描述】:向 jsoncpp 数组添加值后出现问题。接下来是我的代码:
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include "jsoncpp/dist/jsoncpp.cpp"
#include "jsoncpp/dist/json/json.h"
#include "jsoncpp/dist/json/json-forwards.h"
using namespace std;
void printArray(const char *measure, float **arr, int rows, int cols)
int i,j;
cout << endl;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
cout << arr[i][j] << "\t";
cout << endl;
cout << endl;
if (measure == "ECG")
int i,j;
Json::Value ECG;
Json::Value time(Json::arrayValue);
Json::Value values(Json::arrayValue);
for (i = 0; i < rows; i++)
for (j = 0; j < 1; j++)
time.append(Json::Value(arr[i][j]));
for (i = 0; i < rows; i++)
for (j = 1; j < 2; j++)
values.append(Json::Value(arr[i][j]));
cout << endl << time << endl;
cout << endl << values << endl;
int main()
int i,j;
int rows, cols;
const char *measur;
rows = 10;
cols = 2;
float **array = new float *[rows];
for(int i = 0; i < rows; i++)
array[i] = new float [cols];
for(int j = 0; j < cols; j++)
array[i][j]=(i+j)/10.0;
measur = "ECG";
printArray(measur, array, rows, cols);
编译并运行后,我有以下输出:
0 0.1
0.1 0.2
0.2 0.3
0.3 0.4
0.4 0.5
0.5 0.6
0.6 0.7
0.7 0.8
0.8 0.9
0.9 1
[
0.0,
0.10000000149011612,
0.20000000298023224,
0.30000001192092896,
0.40000000596046448,
0.5,
0.60000002384185791,
0.69999998807907104,
0.80000001192092896,
0.89999997615814209
]
[
0.10000000149011612,
0.20000000298023224,
0.30000001192092896,
0.40000000596046448,
0.5,
0.60000002384185791,
0.69999998807907104,
0.80000001192092896,
0.89999997615814209,
1.0
]
如您所见,在向 json 数组添加值之前,一切正常,但之后,存在不同的值。现在它是数据的测试样本,但它将是一个库,将从 RapsberryPi 的 ECG、Pulseoximeter、AirFlow 等模块获取数据,因此“值”数组中的数据将类似于 0.14453453、0.23546456 等,我必须防止那样的情况。我的价值观必须尽可能准确。
谢谢。
【问题讨论】:
字符串与浮点表示。要么存储字符串,要么接受浮点数和双精度数并不总是完全匹配字符串。它们将是 +/- 少量。 【参考方案1】:浮点数和双精度数不存储以 10 为底的数字。他们使用的底数 2 有时会非常接近,但 +/- 一个很小的值。浮点维基:https://en.wikipedia.org/wiki/Floating-point_arithmetic
您通常可以稍后通过使用 sprintf 或类似方法将浮点数转换回字符串来取回相同的值(用于显示目的)。看起来您正在读取 1 个十进制数字,例如:
sprintf(stringout, "%.1f", floatin);
在比较浮点数和双精度数时,请始终牢记这个“不完全相等”的事实。与其问“是 x == y”,不如问“是 x == y +/- 一些容差值,例如 0.0001”
【讨论】:
【参考方案2】:好的,我将 floatarray 类型更改为 double,现在我的准确度要好得多。这对我来说很好。现在,请告诉我,如何将只有 8 位小数的值发送到“值”表?我不想在值数组数据中包含值 = [0.12121212, 0.21212121],但我只想有这样的值 = [0.1212, 0.2121]。我想要做的是在循环中切断“值”表中多余的信息。我的意思是,如何在将数据附加到“值”表时设置数字限制。
【讨论】:
【参考方案3】:像这样以更高的精度打印您的输入值:
cout << std::setw(11) << std::setprecision(9) << arr[i][j] << "\t";
其他一切正常。
编辑:这是没有预防措施的,因为您无法 100% 准确地以二进制表示 0.9。在由 b1*1/2 + b2*1/4 + b3 * 1/4 + ... 组成的二进制分数中 如果您从传感器读取数据,那么它已经是 0.1212121212.... 如果您想向用户显示经过整理的数据,您可以使用与上述相同的技巧。但是如果你仍然想只使用 10-15 位小数来存储,那么你需要使用定点数学,但我敢打赌你不会。
【讨论】:
好的,所以这个技巧告诉我,即使我的 arr 中的数据也与应有的不同。但是您可以看到,在我生成“arr”时的主函数中应该有0.1、0.2、0.3、0.4等......那么如何获得更准确的数据?我的意思是......当我创建数组时,例如有 0.9,但是在将它发送到函数之后,在同一个地方有 0.89999997615814209。如何防止这种情况?如何获得约 10-15 个小数位的准确度?以及如何使用 for ex 将数据从 arr 添加到 jsoncpp 数组。精确到小数点后 8 位? 好的,我解决了这个问题,只是将数组类型从浮点数更改为双精度数。现在我有不同的问题 - 如何在将数据附加到“值”表期间设置数字限制?由于“双”,我的所有数据都将精确到小数点后 16 位,我想在 for 循环之前或期间减少多余的数字。 @Fempter 有什么多余的?你是对的,double 最多可以存储 16 位十进制数字,所以这是你将拥有的最大位数,当然以指数为模。如果你不想用这么多数字让用户难堪,那么这不是关于存储,而是关于 UI。您可以使用setprecision
相应地格式化字符串。
是的,我想在我的 for 循环中使用 setprecision
。我想在这里使用这个:time.append(Json::Value(arr[i][j]));
因为如您所见,我在time
和values
表中的数据不是我想要的。我想追加到time
表数据,精度为3,但到values
表,精度为6。我该怎么做?
@Fempter,这并不容易做到。我建议你开始新的问题。有很多可能性可以做到这一点,比如使用定点算法或将双精度转换为最接近的分数(如 1/3、1/10 等),但所有这些都需要相当大的努力,即使你会使用一些库你需要好好思考如何使用它。以上是关于将它们添加到 C++ 中 JsonCpp 模块中的数组后的错误值的主要内容,如果未能解决你的问题,请参考以下文章