将它们添加到 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])); 因为如您所见,我在timevalues 表中的数据不是我想要的。我想追加到time 表数据,精度为3,但到values 表,精度为6。我该怎么做? @Fempter,这并不容易做到。我建议你开始新的问题。有很多可能性可以做到这一点,比如使用定点算法或将双精度转换为最接近的分数(如 1/3、1/10 等),但所有这些都需要相当大的努力,即使你会使用一些库你需要好好思考如何使用它。

以上是关于将它们添加到 C++ 中 JsonCpp 模块中的数组后的错误值的主要内容,如果未能解决你的问题,请参考以下文章

C++ jsoncpp解析二维数组

C++ jsoncpp 输出名称和值

如何链接jsoncpp?

如何在安卓ndk工程中引入jsoncpp

c++ JsonCpp Parse对Json字符串解析转换判断的补充 Json格式验证

在C++环境中使用JsonCpp读写Json数据