- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我正在使用一个应用程序,它使用 std::stringstream
从文本文件中读取空格分隔的 double
矩阵。该应用程序使用的代码有点像:
std::ifstream file {"data.dat"};
const auto header = read_header(file);
const auto num_columns = header.size();
std::string line;
while (std::getline(file, line)) {
std::istringstream ss {line};
double val;
std::size_t tokens {0};
while (ss >> val) {
// do stuff
++tokens;
}
if (tokens < num_columns) throw std::runtime_error {"Bad data matrix..."};
}
相当标准的东西。我勤奋地编写了一些代码来制作数据矩阵(data.dat
),对每条数据线使用以下方法:
void write_line(const std::vector<double>& data, std::ostream& out)
{
std::copy(std::cbegin(data), std::prev(std::cend(data)),
std::ostream_iterator<T> {out, " "});
out << data.back() << '\n';
}
即使用 std::ostream
。但是,我发现应用程序无法使用此方法读取我的数据文件(抛出上述异常),特别是它无法读取 7.0552574226130007e-321
。
我编写了以下显示行为的最小测试用例:
// iostream_test.cpp
#include <iostream>
#include <string>
#include <sstream>
int main()
{
constexpr double x {1e-320};
std::ostringstream oss {};
oss << x;
const auto str_x = oss.str();
std::istringstream iss {str_x};
double y;
if (iss >> y) {
std::cout << y << std::endl;
} else {
std::cout << "Nope" << std::endl;
}
}
我在 LLVM 10.0.0 (clang-1000.11.45.2) 上测试了这段代码:
$ clang++ --version
Apple LLVM version 10.0.0 (clang-1000.11.45.2)
Target: x86_64-apple-darwin17.7.0
$ clang++ -std=c++14 -o iostream_test iostream_test.cpp
$ ./iostream_test
Nope
我也尝试使用 Clang 6.0.1、6.0.0、5.0.1、5.0.0、4.0.1 和 4.0.0 进行编译,但得到了相同的结果。
使用 GCC 8.2.0 编译,代码可以正常工作:
$ g++-8 -std=c++14 -o iostream_test iostream_test.cpp
$ ./iostream_test.cpp
9.99989e-321
为什么 Clang 和 GCC 之间有区别?这是一个clang bug吗,如果不是,应该如何使用C++流来编写可移植的浮点IO?
最佳答案
如果我们阅读 std::stod throws out_of_range error for a string that should be valid 的答案,我相信 clang 在这里是一致的。它说:
The C++ standard allows conversions of strings to
double
to report underflow if the result is in the subnormal range even though it is representable.7.63918•10-313 is within the range of
double
, but it is in the subnormal range. The C++ standard saysstod
callsstrtod
and then defers to the C standard to definestrtod
. The C standard indicates thatstrtod
may underflow, about which it says “The result underflows if the magnitude of the mathematical result is so small that the mathematical result cannot be represented, without extraordinary roundoff error, in an object of the specified type.” That is awkward phrasing, but it refers to the rounding errors that occur when subnormal values are encountered. (Subnormal values are subject to larger relative errors than normal values, so their rounding errors might be said to be extraordinary.)Thus, a C++ implementation is allowed by the C++ standard to underflow for subnormal values even though they are representable.
我们可以确认我们依赖 strtod from [facet.num.get.virtuals]p3.3.4 :
- For a double value, the function strtod.
我们可以用这个小程序进行测试(现场观看):
void check(const char* p)
{
std::string str{p};
printf( "errno before: %d\n", errno ) ;
double val = std::strtod(str.c_str(), nullptr);
printf( "val: %g\n", val ) ;
printf( "errno after: %d\n", errno ) ;
printf( "ERANGE value: %d\n", ERANGE ) ;
}
int main()
{
check("9.99989e-321") ;
}
结果如下:
errno before: 0
val: 9.99989e-321
errno after: 34
ERANGE value: 34
7.22.1.3p10 中的 C11告诉我们:
The functions return the converted value, if any. If no conversion could be performed, zero is returned. If the correct value overflows and default rounding is in effect (7.12.1), plus or minus HUGE_VAL, HUGE_VALF, or HUGE_VALL is returned (according to the return type and sign of the value), and the value of the macro ERANGE is stored in errno. If the result underflows (7.12.1), the functions return a value whose magnitude is no greater than the smallest normalized positive number in the return type; whether errno acquires the value ERANGE is implementation-defined.
POSIX 使用 that convention :
[ERANGE]
The value to be returned would cause overflow or underflow.
我们可以通过 fpclassify 验证它是否正常。 (see it live)。
关于c++ - 为什么 Clang std::ostream 会写入 std::istream 无法读取的 double 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52410931/
我知道的引用资料在这里: http://clang.llvm.org/docs/ClangCommandLineReference.html http://clang.llvm.org/docs/Di
这两个工具似乎有一些共同的目标,而 documentation of clang-tidy对其功能非常明确,clang-check's有点稀疏。 如果我只能运行这些工具中的一个,同时进行相同的检查,那
我不清楚 clang 使用的汇编器。 AFAIK native 又名 GNU 汇编器和链接器被使用(与 gcc 一起提供)。 clang -v main.c clang version 3.4.2 T
在哪里可以找到 Clang 标志的完整列表? 还有一些,例如 -include-pch,甚至没有在手册页中列出。 :( 我知道 GCC 使用一些相同的标志,但它不包含诸如 -Os 之类的文档,我相信这
大多数成熟的编译器似乎对堆栈变量破坏有很好的支持。 海湾合作委员会:-fstack-protector xlC: -qstackprotect 英特尔:-fstackprotector window
我的命令: /usr/bin/c++ -fPIC -I/Users/me/project/include -I/usr/local/include/opencv \ -I/usr/local/incl
我正在研究 CLang 3.5。我正在尝试获取有关在 C++ 项目中声明的变量的信息。 如何获取 clang::VarDecl 中变量的数据类型或限定类名, clang::FieldDecl或 cla
我正在尝试构建 LLVM 编译器,以便我可以在 Apple M1 上启用 OpenMP。 我正在使用 LLVM 开发树,(因为我最近看到一些 OpenMP 运行时对此进行了处理)。 我已经结束了这个脚
背景: 在 Windows 10 PC 上,我有一个 C++ 代码库。使用 CMAKE 我生成了一个 Mingw-w64 项目(使用 Eclipse IDE)和一个 Visual Studio 201
下面是我想做的。 我想通过使用 cmake 的正确程序检测 clang 来使用 clang/clang++ 进行编译。 请告诉我可以解决我将描述的问题的正确程序。 test environment:
基本问题 我有以下代码 #include #include using namespace std; int main () { int32_t spam; spam=5; cout
当我在xcode中编译.c文件时,出现错误提示: clang error: argument unused during compilation: '-fno-objc-exceptions' [-W
Clang has several kinds of diagnostics ,其中三种主要是错误、警告和注释。 注释通常伴随着某些警告和错误,例如重复定义: error: conflicting t
我正在调整 Clang 工具模板(如 here 所述)以在我的代码中搜索特定的方法调用。为了稍后重写该调用,我想获取调用该方法的参数的类型,以及调用该方法的对象的类型。 我设法找到了一个可以回调以下内
我必须通过在它之前添加一个语句来检测 clang 中的某些语句。我有一个指向 Expr 对象的指针,我需要在包含它的语句之前插入另一个语句。现在我正在使用一种hacky方法,它只是将 SourceLo
类 clang::ASTContext 有一个方法: DynTypedNodeList getParents(const NodeT &Node) 它返回给定 AST 节点的父节点列表。 通常 AST
我想修改代码分析器程序clang-tidy的检查正在做,但是好像是配置文件.clang-tidy的内容正在被忽视。 我通过调用 clang-tidy 创建文件带旗-dump-config并将输出重定向
有没有办法用clang创建一个可以合理地适合页面的调用图? 即给出: #include using namespace std; int main() { int a; cin>>a;
我正在编写一个 Clang 工具,并且试图弄清楚如何在访问程序 AST 的情况下评估字符串文字。给定以下程序: class DHolder { public: DHolder(std::strin
我想在 Clang 中尝试一些新功能,有人提到我 Clang TOT . 现在这可能是一个明显的问题,到底是什么Clang TOT . TOT 一定是一些我不熟悉的首字母缩写词。 任何人都可以启发我吗
我是一名优秀的程序员,十分优秀!