在C++中是否可能使用十六进制浮点值初始化浮点变量?
类似于这样:
double d = 0x011.1; // wrong!
在C++中是否可能使用十六进制浮点值初始化浮点变量?
类似于这样:
double d = 0x011.1; // wrong!
技术规范P0245 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
。
请查看更易读的页面cppreference.com上的浮点文字面值页面。
请参阅 GitHub 上的 C++17 当前工作草案,第§ 2.13.4 浮点字面量章节:https://github.com/cplusplus/draft/raw/master/papers/n4604.pdf。
0x | 0X 十六进制数
0x | 0X 十六进制数 .
0x | 0X 十六进制数(可选) . 十六进制数
十六进制数字序列表示一个没有基数分隔符的整数。对于十六进制浮点文字,指数永远不是可选的:
0x1ffp10
、0X0p-1
、0x1.p0
、0xf.p-1
、0x0.123p-1
、0xa.bp10l
十六进制浮点文字的指数语法形式为
p | P 指数符号(可选) 数字序列
如果存在指数符号,则为 + 或 -
如果存在后缀,则为
f
,F
,l
, 或L
中的一种。 后缀决定了浮点文字的类型:
- (无后缀) 定义 double
f F
定义 floatl L
定义 long double
浮点字面量:
十进制浮点字面量
十六进制浮点字面量
十进制浮点字面量:
小数常量 指数部分(可选) 浮点后缀(可选)
数字序列 指数部分 浮点后缀(可选)
十六进制浮点字面量:
十六进制前缀 十六进制小数常量 二进制指数部分 浮点后缀(可选)
十六进制前缀 十六进制数字序列 二进制指数部分 浮点后缀(可选)
小数常量:
数字序列(可选) . 数字序列
数字序列 .
十六进制小数常量:
十六进制数字序列(可选) . 十六进制数字序列
十六进制数字序列 .
指数部分:
e
符号(可选) 数字序列
E
符号(可选) 数字序列
二进制指数部分:
p
符号(可选) 数字序列
P
符号(可选) 数字序列
符号: 为以下之一
+
-
数字序列:
数字
数字序列 ’ 数字
浮点后缀: 为以下之一
f
l
F
L
1 浮点字面量由一个可选前缀、一个整数部分、一个基数点、一个小数部分、一个
e
、E
、p
或P
、一个可选的带符号整数指数和一个可选的类型后缀组成。如果没有前缀,则整数部分和小数部分均由十进制(十进制)数字序列组成,否则由十六进制(十六进制)数字序列组成。在前一种情况下,字面量是一个“十进制浮点字面量”,在后一种情况下,字面量是一个“十六进制浮点字面量”。在数字序列或十六进制数字序列中可选的分隔单引号在确定其值时被忽略。[例子:字面量1.602’176’565e-19
和1.602176565e-19
具有相同的值。—结束例子] 整数部分和小数部分(不是两者都)可以省略。十进制浮点字面量可以省略基数点或字母 e 或 E 和指数(不是两者都)。十六进制浮点字面量可以省略基数点(但不是正如 unwind 所建议的,您可以使用
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'; }
strtof
(它产生float
,但OP可能需要double
)。这将生成除使用支持十六进制浮点数的C++编译器或使用自定义预处理器将十六进制浮点数转换为十进制数(并使用将十进制数转换为浮点数的C++编译器)之外的最佳代码。 - Eric Postpischil
int
转换为float
,但需要了解给定平台上float
的字节表示方式。 - Creris