Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+中的Json+;:将数字解析为字符串以避免浮点不准确_C++_Json_Double_Fixed Point_Jsoncpp - Fatal编程技术网

C++ C+中的Json+;:将数字解析为字符串以避免浮点不准确

C++ C+中的Json+;:将数字解析为字符串以避免浮点不准确,c++,json,double,fixed-point,jsoncpp,C++,Json,Double,Fixed Point,Jsoncpp,我正在处理加密货币RPC并接收json数据,如下所示: { ... "amount": 1.34000000, "confirmations": 230016, "spendable": true, "solvable": true ... } 使用库或获取解析为双精度的数字。发生这种情况时,由于双精度问题,结果为:1.34000000000000001。一般来说,这对金融交易来说是灾难性的,是不可接受的 我已经有了一个定点库,它可以接受一个有效的字符串,并在内部将其视

我正在处理加密货币RPC并接收json数据,如下所示:

{
  ...
  "amount": 1.34000000,
  "confirmations": 230016,
  "spendable": true,
  "solvable": true
  ...
}
使用库或获取解析为
双精度的数字。发生这种情况时,由于双精度问题,结果为:
1.34000000000000001
。一般来说,这对金融交易来说是灾难性的,是不可接受的


我已经有了一个定点库,它可以接受一个有效的字符串,并在内部将其视为一个整数。有没有一种方法可以让Jsoncpp(或任何其他json库)将选定的数字json值作为字符串,以便以正确的方式以固定的精度处理它们?

json库中似乎没有解决方案,因此我不得不自己修改数字并用引号将其括起来。我将此函数应用于响应以实现此目的

[](std::string& jsonStr) {
        // matches "amount" field in json
        static std::regex reg(R"((\s*\"amount\"\s*:)\s*(\d*\.{0,1}\d{0,8})\s*)");
        jsonStr = std::regex_replace(jsonStr, reg, "$1\"$2\"");
    };
现在它可以正常工作了。

我喜欢。免责声明是我写的

它支持您正在寻找的内容。
您可以告诉解析器对一个类使用标准的输入/输出操作符(然后您可以自己定义)

例如:

#include "ThorSerialize/JsonThor.h"
#include "ThorSerialize/SerUtil.h"
#include <sstream>
#include <iostream>
#include <string>
#include <map>

struct FixedPoint
{
    int     integerPart;
    int     floatPart;
    friend std::istream& operator>>(std::istream& stream, FixedPoint& data)
    {
        // This code assumes <number>.<number>
        // Change to suite your needs.
        char c;
        stream >> data.integerPart >> c >> data.floatPart;
        if (c != '.')
        {
            stream.setstate(std::ios::failbit);
        }

        return stream;
    }
};
// This declaration tells the serializer to use operator>> for reading
// and operator<< for writing this value.
// Note: The value must still conform to standard Json type
//       true/false/null/integer/real/quoted string
ThorsAnvil_MakeTraitCustom(FixedPoint);

struct BitCoin
{
    FixedPoint  amount;
    int         confirmations;
    bool        spendable;
    bool        solvable;
};
// This declaration tells the serializer to use the standard
// built in operators for a struct and serialize the listed members.
// There are built in operations for all built in types and std::Types
ThorsAnvil_MakeTrait(BitCoin, amount, confirmations, spendable, solvable);

本机jsoncpp解决方案是RTFM!!!(例如,此处:)

这将设置writer float精度,以避免打印双精度表示中的小截断错误。e、 例如,不是json字段

“金额”:13400000000000001

您现在将获得

“金额”:1340000000000000


根据需要。

我不确定,但您可能可以运行预分析,并将
的“金额”:134000000更改为
“金额”:“134000000”
@NathanOliver sure。这将是一个我最后要做的黑客攻击。如果您将值存储为double,那么即使您将值解析为字符串,也会发生这种情况。一旦你把它放到一个双精度浮点上,就有了一个有限的分辨率。这就是为什么金融应用程序不使用实数(它们使用整数或BCD(二进制编码的小数))。您可以乘以
100000000
并将其存储为整数。@但您似乎误解了发生的事情。请允许我解释一下。将数字乘以10000000后存储这些数字。。。基本上被称为“定点精度”,这就是我在问题中提到的(例如,比特币是如何运作的,其中最小的可交易整数单位称为satoshi)。我永远都不想把东西放在双人房里。问题是,我想直接从字符串转换到定点精度,而不必经过双精度转换,所有json库似乎都是在未经我同意的情况下进行的。
int main()
{
    using ThorsAnvil::Serialize::jsonImport;
    using ThorsAnvil::Serialize::jsonExport;

    std::stringstream file(R"(
        {
            "amount": 1.34000000,
            "confirmations": 230016,
            "spendable": true,
            "solvable": true
        }
    )");

    BitCoin     coin;
    file >> jsonImport(coin);

    std::cout << coin.amount.integerPart << " . " << coin.amount.floatPart << "\n";
}
> g++ -std=c++1z 51087868.cpp -lThorSerialize17
Json::StreamWriterBuilder builder;
builder["commentStyle"] = "None";
builder["indentation"] = "   ";
builder["precision"] = 15;