c++ - Explicit specification of the double precision representation used by compiler
问题描述
I've recently come across the problem that visual-c++
does not seem to be IEEE 754 compliant, but instead uses subnormal representation. That is, double precision floats in it do not have the usual representation of 1 sign bit, 11 exponent bits and 52 explicitly stored significant decimal bits, see below.
As gcc
and clang
are however compliant and consistent cross-platform behaviour is highly desired I would like to know whether it is possible to force visual-c++
to use the normal representation. Alternatively making gcc
and clang
use the subnormal representation would of course also solve the problem.
The issue of the different double representations can be reproduced in visual-c++
, gcc
and clang
using the following code:
#include <iostream>
#include <string>
int main()
{
try {
std::stod("8.0975711886543594e-324");
std::cout << "Subnormal representation.";
} catch (std::exception& e) {
std::cout << "Normal representation.";
}
return 0;
}
Is a representation specification to produce consitent behaviour in all three cases at all possible?
Edit: As geza pointed out, this appears a problem in the different implementations of std::stod
, which would then make the question if there is any way to make std::stod
behave consistently without having to implement a seperate wrapper for it.
解决方案
不幸的是,std::stod
它的设计很糟糕,因为无法确定是什么导致了std::out_of_range
异常。
我建议你strtod
改用。虽然标准中没有指定此函数应该对次正规数做什么,但它通常对次正规数表现良好(这意味着它返回次正规数)。这个函数的好处是它对超出范围的情况返回有意义的结果,因此可以确定超出范围的原因。
如果要处理超出范围的情况,则需要errno
检查ERANGE
. 请注意,如果结果是次正规数/零数,那么可能errno
会设置为ERANGE
,您应该忽略它(您可以使用 来检查fpclassify
)。
所以逻辑是这样的:
double r = strtod(string, &end);
// here, check for end to know about invalid strings
if (errno==ERANGE) { // out-of-range (overflow, underflow)
int c = fpclassify(r);
if (c!=FP_SUBNORMAL&&c!=FP_ZERO) { // let's filter out underflow cases
// "real" out of range handling here, just overflow
}
}
推荐阅读
- angular - 使用 queryParams 重定向到 url
- apostrophe-cms - 多个小部件视图
- active-directory - 使用 Halyard 的 Spinnaker LDAP
- wix - 卸载后程序文件中存在空目录
- xml - 简单的前同级选择返回意外结果
- android - 从gradle中的多个依赖项中排除同一组?
- c# - 在 Xamarin.Forms 中使用 View Model 的属性绑定到 StaticResource?
- git - 如何在 Git 中推送到远程后更改提交消息
- python - 在 python 客户端套接字程序中找不到错误
- javascript - 使用单选按钮和复选框从 HTML 生成 PDF