十六进制浮点文字

Hexadecimal floating point literals

本文关键字:文字 十六进制      更新时间:2023-10-16

是否可以用C++中的十六进制浮点值初始化浮点变量?

类似这样的东西:

double d = 0x011.1; // wrong!

2016年2月,在佛罗里达州杰克逊维尔举行的ISO C++标准委员会上,C++的十六进制浮点文字技术规范P0245已被投票通过C++17。

C99语言也有这个特性,并且C++特性是兼容的。

然而,正如Lưu Vĩnh Phúc的评论所指出的,语法0x011.1不是标准的一部分。二进制指数对于十六进制浮点文字是必需的。一个原因是为了避免CCD_ 3内的尾随CCD_。是小数部分的十六进制数字F还是表示float的浮动后缀
因此,在p后面加上一个正小数或负小数,例如:0x011.1p0

请参阅cppreference.com上可读性更强的浮动文字页面。

0x | 0X hex-digit-sequence
0x | 0X hex-digit-sequence .
0x | 0X hex-digit-sequence(optional) . hex-digit-sequence

十六进制数字序列,表示不带基数分隔符的整数。对于十六进制浮点文字:0x1ffp100X0p-10x1.p00xf.p-10x0.123p-10xa.bp10l,指数从来都不是可选的

十六进制浮点文字的指数语法的形式为
p | P exponent-sign(optional) digit-sequence

指数符号(如果存在)为+或-

后缀(如果存在)是fFF0或L之一。后缀决定浮点文字的类型:

  • (无后缀)定义双
  • f F定义浮点
  • l L定义长双

另请参阅当前的工作草案C++17,章节§2.13.4 GitHub上的浮动文本:https://github.com/cplusplus/draft/raw/master/papers/n4604.pdf

浮动文字:
/emsp十进制浮动文字
/emsp十六进制浮点文字
十进制浮点文字:
/emsp分数常数指数部分opt浮动后缀option
/emsp数字序列指数部分浮动后缀opt
十六进制浮动文字:
/emsp十六进制前缀十六进制分数常量二进制指数部分浮动后缀opt
/emsp十六进制前缀十六进制数字序列二进制指数部分浮动后缀opt
分数常数:
/emsp数字序列opt。数字序列
/emsp数字序列
十六进制分数常数:
/emsp十六进制数字序列opt。十六进制数字序列
/emsp十六进制数字序列
指数部分:符号opt数字序列
/emsp;E符号opt数字序列
二进制指数部分:
/emsp;p符号opt数字序列
/emsp;P符号opt数字序列
标记:
/emsp;+-
数字序列:
/emsp数字
/emsp数字序列'opt数字
浮动后缀:
/emsp;0x011.1F0lFL

1浮动文字由指定基数、整数部分、基点、小数部分、eEpP的可选前缀、可选带符号整数指数和可选类型后缀组成。如果没有前缀,整数和小数部分都由十进制(以十为基数)数字组成,如果前缀是0x0X,则由十六进制(以十六为基数)的数字组成。在前一种情况下,文本是十进制浮动文本,在后一种情况中,文本是十六进制浮动文本。可选以数字序列十六进制分隔单引号-数字序列在确定其值时被忽略。[示例:文字1.602’176’565e-191.602176565e-19具有相同的值。--结束示例]可以省略整数部分或小数部分(不能同时省略)。小数点或字母e或e和指数(不能同时省略)都可以从十进制浮点文字中省略。可以从十六进制浮点文字中省略基数点(而不是指数)。整数部分、可选的基数点和可选的小数部分构成浮动文字的有效位。在十进制浮动文字中,指数(如果存在)表示有效位要缩放的10的幂。在十六进制浮动文字中,指数表示有效位要缩放的2的幂。[示例:文字49.6250xC.68p+2具有相同的值。--结束示例]如果缩放值在其类型的可表示值范围内,则结果为缩放值(如果可表示),否则为最接近缩放值的较大或较小可表示值(以实现定义的方式选择)。除非由后缀明确指定,否则浮动文字的类型为double。后缀fF指定float,后缀lL指定long double。如果缩放后的值不在其类型的可表示值范围内,则程序格式不正确。

根据建议,您可以使用strtof()。以下代码段解码十六进制浮点文字(不带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';
}

不,C++不支持文字,它不是标准的一部分。

一个不可移植的解决方案是使用一个编译器将其添加为扩展(GCC会这样做)。

一种可移植的解决方法是在运行时使用例如strtof()strtod()来解析double的字符串文本。

正如注释中所指出的,您也可以选择将常量存储在C文件中。但是,这样做需要您能够访问C99编译器,因为十六进制浮点文字是C99级别的特性。由于带有新C++编译器但没有C99编译器(读作:Visual Studio)的环境非常常见,因此这可能不是一个可行的解决方案。

更新:C++17支持十六进制浮点文字。