Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.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++_Floating Point - Fatal编程技术网

C++ 用于精确浮点数字打印的常用函数

C++ 用于精确浮点数字打印的常用函数,c++,floating-point,C++,Floating Point,弗洛里安·洛伊奇有一个很棒的作品叫做。在将任何类型的双精度字符打印到字符串中时,这听起来非常有用。我想包括我在内的许多人直到最近都只知道像使用setprecisionon(n)或printf(“%0.nf”)设置固定精度,并且经常选择n太大而得到浮点不精确,或者太小而切断有价值的数据。在C++标准(包括即将到来的)、Boost、LIBC或某个容易到达和测试的地方,我想知道类似的事情吗? 用于精确浮点数字打印的常用函数 Post最初标记为[C]和[C++] // Hexadecimal/deci

弗洛里安·洛伊奇有一个很棒的作品叫做。在将任何类型的双精度字符打印到字符串中时,这听起来非常有用。我想包括我在内的许多人直到最近都只知道像使用
setprecisionon(n)
printf(“%0.nf”)
设置固定精度,并且经常选择
n
太大而得到浮点不精确,或者太小而切断有价值的数据。在C++标准(包括即将到来的)、Boost、LIBC或某个容易到达和测试的地方,我想知道类似的事情吗? 用于精确浮点数字打印的常用函数

Post最初标记为[C]和[C++]

 // Hexadecimal/decimal exponential output.
 printf("%a\n", value);  

 // Decimal exponential output with sufficient precision to distinguish against other double
 printf("%.*e\n", DBL_DECIMAL_DIG - 1, double_value);  

 // Decimal sometimes exponential output with sufficient precision to distinguish against other double
 printf("%.*g\n", DBL_DECIMAL_DIG, double_value);  


所有有限浮点值都是精确的。很少有人需要把它精确地看作小数点。这是.

我认为在标准C++库中没有任何真正好的解决方案。 我使用的技巧是尝试几种不同的格式,然后选择最短的文本表示法当往返时,文本表示法具有完全相同的值。我用它保存在我的文本文件(XML)输出中

这有时意味着选择精确的十六进制浮点表示。(可能是您用例的交易破坏者。)

下面是代码,我添加了一个表来生成一些示例,如果它们是最短的,则将它们标记为
*
,如果它们不是往返的,则使用警告标记

#include <iomanip>
#include <ios>
#include <iostream>
#include <sstream>

using std::cout;
using std::defaultfloat;
using std::fixed;
using std::hexfloat;
using std::istringstream;
using std::left;
using std::scientific;
using std::setw;
using std::string;
using std::stringstream;

enum class cap { title, middle, end };

static void print(const char* text, double num, cap c) {
    stringstream ss;
    ss << fixed << num;
    auto s = ss.str();
    double fn = stod(s);
    size_t flen = s.length();
    string falert = "";
    if (fn != num) { falert = "/!\\"; flen += 100; }

    ss.str("");
    ss.clear();
    ss << scientific << num;
    s = ss.str();
    double sn = stod(s);
    size_t slen = s.length();
    string salert = "";
    if (sn != num) { salert = "/!\\"; slen += 100; }

    ss.str("");
    ss.clear();
    ss << hexfloat << num;
    s = ss.str();
    double hn = stod(s);
    size_t hlen = s.length();
    string halert = "";
    if (hn != num) { halert = "/!\\"; hlen += 100; }

    ss.str("");
    ss.clear();
    ss << defaultfloat << num;
    s = ss.str();
    double dn = stod(s);
    size_t dlen = s.length();
    string dalert = "";
    if (dn != num) { dalert = "/!\\"; dlen += 100; }

    char gbuf[256];
    sprintf(gbuf, "%g", num);
    s = gbuf;
    double gn = stod(s);
    size_t glen = s.length();
    string galert = "";
    if (gn != num) { galert = "/!\\"; glen += 100; }

    if (flen <= slen && flen <= hlen && flen <= dlen) falert += "*";
    if (slen <= flen && slen <= hlen && slen <= dlen) salert += "*";
    if (hlen <= flen && hlen <= slen && hlen <= dlen) halert += "*";
    if (dlen <= flen && dlen <= hlen && dlen <= slen) dalert += "*";
    if (glen <= dlen && glen <= flen && glen <= hlen && glen <= slen) galert += "*";

    if (c == cap::title) cout <<
    "┌──────────┬────────────┬──────────────────────────┐\n"
    "│  number  │   iomanip  │      representation      │\n"
    "├──────────┼────────────┼──────────────────────────┤\n"
    ;
    cout << left
    << "│ " << setw(8) << text << " │ fixed      │ " << setw(24) << fixed        << num << " │" << falert << "\n"
    << "│ " << setw(8) << text << " │ scientific │ " << setw(24) << scientific   << num << " │" << salert << "\n"
    << "│ " << setw(8) << text << " │ hexfloat   │ " << setw(24) << hexfloat     << num << " │" << halert << "\n"
    << "│ " << setw(8) << text << " │ default    │ " << setw(24) << defaultfloat << num << " │" << dalert << "\n"
    << "│ " << setw(8) << text << " │ %g         │ " << setw(24) << gbuf                << " │" << galert << "\n"
    ;
    cout << (c != cap::end ?
    "├──────────┼────────────┼──────────────────────────┤\n" :
    "└──────────┴────────────┴──────────────────────────┘\n" );
}

static void table() {
    print("0.0", 0.0, cap::title);
    print("0.01", 0.01, cap::middle);
    print("0.00001", 0.00001, cap::middle);
    print("1e99"   , 1.e+99, cap::middle);
    print("0.1"    , 0.1, cap::middle);
    print("0.2"    , 0.2, cap::middle);
    print("0.3"    , 0.3, cap::middle);
    print("0.4"    , 0.4, cap::middle);
    print("0.5"    , 0.5, cap::middle);
    print("0.6"    , 0.6, cap::middle);
    print("0.7"    , 0.7, cap::middle);
    print("0.8"    , 0.8, cap::middle);
    print("0.9"    , 0.9, cap::middle);
    print("NTSC"   , 30.0/1001.0, cap::middle);
    print("1/3"    , 1.0/3.0, cap::end);
}

int main() {
    table();
}
#包括
#包括
#包括
#包括
使用std::cout;
使用std::defaultfloat;
使用std::fixed;
使用std::hexfloat;
使用std::istringstream;
使用std::left;
使用std::scientific;
使用std::setw;
使用std::string;
使用std::stringstream;
枚举类cap{title,middle,end};
静态无效打印(常量字符*文本,双数字,大写c){
细流ss;

在阅读PDF之前先阅读ss:
printf(“%g”,value)使用默认精度6,即,你必须指定精度。这能回答你的问题吗?C和C++是不同的语言,同时产生不同的答案。我已经删除了C标签,因为这个问题特别提到C++标准,因此似乎是针对C++的。“正确的打印成为许多语言规范的一部分,而且所有主要的C库(以及所有依赖于
printf
函数的程序)现在都采用了准确的算法并打印正确的结果。”OP可能需要生成唯一的数字数的算法,这些数字需要唯一地标识转换的特定数字的原始值。C++库例程不这样做,即使它们正确地循环(标准不需要,除非它已经升级)。@EricPostpischil使用非OP编辑的语言标记,这个C答案可能仍然会为OP带来一些启示。至于OP真正想要什么,如果它不是“用于精确浮点数字打印的常用功能”也可能会演变。@chux谢谢。但这不起作用,它不能准确地表示数字。例如,
100.74
使用这种方法会以单精度错误地表示。@Yuki当然这是一个内部表示的问题。大多数十进制分数只能用二进制分数近似,这就是有限精度IEEE-754二进制浮点数的含义。这似乎是“浮点数学坏了吗?”@njuffa我不认为数学坏了。我知道浮点内部工作的一些基本原理。你可以试着阅读这篇论文的乞求,以了解我所说的内容。