十六进制浮点字面量

Posted

技术标签:

【中文标题】十六进制浮点字面量【英文标题】:Hexadecimal floating point literals 【发布时间】:2014-02-26 21:40:43 【问题描述】:

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

类似这样的:

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

【问题讨论】:

不是那么简单,但你可以将int重新解释为float,但你需要知道给定平台上float的字节表示 您可以在 C99 和 C++17 中使用,但不能在您的语法中使用 en.cppreference.com/w/cpp/language/floating_literal 【参考方案1】:

技术规范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-sequence0x | 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

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

后缀(如果存在)是 fFlL 之一。后缀决定了浮点字面量的类型:

(无后缀)定义双精度 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-suffixopthexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part floating-suffixopt小数常数:数字序列opt 。数字序列数字序列。十六进制分数常数:十六进制数字序列opt 。十六进制数字序列十六进制数字序列。指数部分:e signopt 数字序列E signopt 数字序列二进制指数部分:p signopt 数字序列P signopt 数字序列sign: 之一+-数字序列:数字digit-sequence 'opt digitfloating-suffix: 之一flFL

1 浮动文字由一个可选前缀组成,该前缀指定一个基数、一个整数部分、一个小数点、一个小数部分、eEp 或 @987654363 @,一个可选的有符号整数指数和一个可选的类型后缀。如果没有前缀,则整数和小数部分都由十进制(以十进制为底)数字组成,如果前缀为 0x0X,则由十六进制(以十六进制为底)数字组成。前一种情况下的文字是十进制浮动文字,后一种情况下是十六进制浮动文字digit-sequencehexadecimal- 中可选的分隔单引号 确定其值时忽略数字序列。 [ 示例: 文字 1.602’176’565e-191.602176565e-19 具有相同的值。 — end example ] 可以省略整数部分或小数部分(不能同时省略两者)。小数点或字母 e 或 E 和指数(不是两者)都可以从十进制浮点文字中省略。可以从十六进制浮动文字中省略小数点(但不是指数)。整数部分、可选的小数点和可选的小数部分,构成了浮动文字的 significand。在十进制浮点字面量中,指数(如果存在)表示有效数要缩放的 10 的幂。在十六进制浮点字面量中,指数表示要缩放有效数字的 2 的幂。 [ 示例: 文字 49.6250xC.68p+2 具有相同的值。 — 结束示例 ] 如果缩放值在其类型的可表示值范围内,则结果是缩放值(如果可表示),否则选择最接近缩放值的较大或较小的可表示值,在实现定义的方式。 浮动文字的类型是double,除非后缀明确指定。后缀fF 指定float,后缀lL 指定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';

【讨论】:

【参考方案2】:

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

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

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

正如评论中指出的,您还可以选择将常量存储在 C 文件中。这样做需要您访问 C99 编译器,因为十六进制浮点文字是 C99 级别的功能。由于具有新 C++ 编译器但没有 C99 编译器(阅读:Visual Studio)的环境很常见,这可能不是一个可行的解决方案。

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

【讨论】:

如果要使用运行时解决方案,不妨使用所需的十六进制浮点数在 C 中简单地定义外部浮点对象,然后将它们链接进去。这至少与strtof(产生float,但OP 可能需要double)不同,运行时成本非常低。除了使用支持十六进制浮点的 C++ 编译器或使用自定义预处理器将十六进制浮点转换为十进制(以及使用将十进制数字准确转换为浮点的 C++ 编译器)之外,这将生成可能的最佳代码。 当然,C++11 有用户定义的文字。那些支持你希望他们支持的任何东西。十六进制浮点数很容易。 @MSalters 哦。 This page 不同意,但请随时详细说明或发布工作实现的链接,我将进行编辑。 @unwind:该页面没有异议,它只是指出您无法使用 C++11 用户定义文字实现 C 内置语法。另外,请阅读有关“原始”文字的部分。 C++17 将支持十六进制浮点数。

以上是关于十六进制浮点字面量的主要内容,如果未能解决你的问题,请参考以下文章

JS中六种数据类型——NumberstringObject

3.Javascript数据类型之进制数和字符串

iOS 中的特殊字面量表示方法

JS中六种数据类型——Number (转)

C++ 中的二进制字面量

08 常量