技术规范P0245 Hexadecimal floating literals for C++ 已于 2016 年 2 月在佛罗里达州杰克逊维尔的 ISO C++ 标准委员会投票成为 C++17。
C99语言也有这个特性,兼容C++特性。
但是,正如Lưu Vĩnh Phúc 的评论所指出的,语法0x011.1 不是标准的一部分。对于十六进制浮点文字,二进制指数是强制性的。一个原因是避免0x011.1F 中尾随F 的歧义。是小数部分的十六进制数字F还是浮点后缀含义float?
因此附加p 后跟一个正数或负数十进制数,例如:0x011.1p0。
查看更易读的页面floating literal page on cppreference.com。
0x | 0X hex-digit-sequence
0x | 0X hex-digit-sequence .
0x | 0X hex-digit-sequence(optional) . hex-digit-sequence
十六进制数字序列表示没有基数分隔符的整数。对于十六进制浮点文字,指数永远不是可选的:0x1ffp10、0X0p-1、0x1.p0、0xf.p-1、0x0.123p-1、0xa.bp10l
十六进制浮点字面量的指数语法格式为
p | P exponent-sign(optional) digit-sequence
指数符号(如果存在)是 + 或 -
后缀(如果存在)是 f、F、l 或 L 之一。后缀决定了浮点字面量的类型:
- (无后缀)定义双精度
-
f F 定义浮点数
-
l L 定义 long double
另见当前工作草案 C++17,章节 § 2.13.4 Floating literals 在 GitHub:https://github.com/cplusplus/draft/raw/master/papers/n4604.pdf
浮动文字:
十进制浮点字面量
十六进制浮动文字
十进制浮动文字:
分数常数指数部分opt 浮动后缀opt
数字序列指数部分浮动后缀opt
十六进制浮动文字:
hexadecimal-prefix hexadecimal-fractional-constant binary-exponent-part floating-suffixopt
hexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part floating-suffixopt
小数常数:
数字序列opt 。数字序列
数字序列。
十六进制分数常数:
十六进制数字序列opt 。十六进制数字序列
十六进制数字序列。
指数部分:
e signopt 数字序列
E signopt 数字序列
二进制指数部分:
p signopt 数字序列
P signopt 数字序列
sign: 之一
+-
数字序列:
数字
digit-sequence 'opt digit
floating-suffix: 之一
flFL
1 浮动文字由一个可选前缀组成,该前缀指定一个基数、一个整数部分、一个小数点、一个小数部分、e、E、p 或 @987654363 @,一个可选的有符号整数指数和一个可选的类型后缀。如果没有前缀,则整数和小数部分都由十进制(以十进制为底)数字组成,如果前缀为 0x 或 0X,则由十六进制(以十六进制为底)数字组成。前一种情况下的文字是十进制浮动文字,后一种情况下是十六进制浮动文字。 digit-sequence 或 hexadecimal- 中可选的分隔单引号
确定其值时忽略数字序列。 [ 示例: 文字 1.602’176’565e-19 和 1.602176565e-19 具有相同的值。 — end example ] 可以省略整数部分或小数部分(不能同时省略两者)。小数点或字母 e 或 E 和指数(不是两者)都可以从十进制浮点文字中省略。可以从十六进制浮动文字中省略小数点(但不是指数)。整数部分、可选的小数点和可选的小数部分,构成了浮动文字的 significand。在十进制浮点字面量中,指数(如果存在)表示有效数要缩放的 10 的幂。在十六进制浮点字面量中,指数表示要缩放有效数字的 2 的幂。 [ 示例: 文字 49.625 和 0xC.68p+2 具有相同的值。 — 结束示例 ] 如果缩放值在其类型的可表示值范围内,则结果是缩放值(如果可表示),否则选择最接近缩放值的较大或较小的可表示值,在实现定义的方式。
浮动文字的类型是double,除非后缀明确指定。后缀f 和F 指定float,后缀l 和L 指定long double。如果缩放后的值不在其类型的可表示值范围内,则程序格式错误。
正如unwind 所建议的,您可以使用strtof()。以下 sn-p 解码十六进制浮动文字(无 C++17):
#include <iostream>
#include <cstdlib>
#include <cstdio>
int main(int argc, char *argv[])
{
if (argc != 2)
{
std::cout <<"Usage: "<< argv[0] <<" 0xA.Bp-1 => Decode hexfloat" "\n";
return 1;
}
long double l;
double d;
float f;
std::cout <<"Decode floating point hexadecimal = "<< argv[1];
//std::istringstream(argv[1]) >> std::hexfloat >> d;
l = std::strtold(argv[1],NULL); if(errno == ERANGE) std::cout << "\n" "std::strtold() range error";
d = std::strtod (argv[1],NULL); if(errno == ERANGE) std::cout << "\n" "std::strtod() range error";
f = std::strtof (argv[1],NULL); if(errno == ERANGE) std::cout << "\n" "std::strtod() range error";
std::cout <<"\n" "long double = "<< std::defaultfloat << l <<'\t'<< std::hexfloat << l
<<"\n" "double = "<< std::defaultfloat << d <<'\t'<< std::hexfloat << d
<<"\n" "float = "<< std::defaultfloat << f <<'\t'<< std::hexfloat << f <<'\n';
}