如何用C ++编写八进制浮点文字?

时间:2015-09-17 08:24:56

标签: c++ floating-point octal

不知怎的,我总是假设浮点和整数值的处理方式相同,只有一个会有'。'字符。

所以对于像这样的代码:

auto i = 0100;
std::cout << i;

我得到了预期的输出64;

但是,当我尝试以下代码时:

auto d = 0100.0;
std::cout << d;

我得到输出100,这不是预期的。现在有可能浮点部分没有处理前导0.所以我尝试了一些真正应该有效的东西:

auto d = 1.0e-010;
std::cout << d;

由于exponent本身实际上是一个整数值,因此理解八进制值是合理的,但输出为1e-10

这是来自标准还是来自g ++(我的编译器)的问题?我将如何编写八进制浮点数?

十六进制似乎表现不同:

auto d = 0x100.0;

提供error: hexadecimal floating constants require an exponent

然而:

auto d = 0x1e3;
std::cout << d;

生成483。而

auto d = 0x1e0x3;

提供error: unable to find numeric literal operator ‘operator"" x3’

3 个答案:

答案 0 :(得分:3)

浮点文字不能用C ++编写的八进制文件。你必须满足于十进制。

标准C ++也不允许使用十六进制浮点文字。但是,C确实(自C99起)和支持它的编译器也可能允许C ++中的十六进制作为语言的扩展。

  

十六进制似乎表现不同

是。有关如何编写十六进制浮点文字的详细信息,请参阅this answer

答案 1 :(得分:1)

你可以自己使用C ++ 11的用户自定义文字。

#include <iostream>
#include <cmath>
using namespace std;

long double operator"" _oct (long double oct)
{
    int i = 0;
    long double rem, fract, decimal = 0.0;
    long whole = (long)oct;
    fract = oct - whole;

    // whole part
    while (whole != 0)
    {
        rem = fmod(whole,10);
        whole/=10;
        decimal += rem*pow(8,i++);
    }
    i = 1; 
    // fractional part
    while(fract != 0){
        fract *= 10;
        rem = round(fract);
        decimal += rem*pow(8,-i++);
        fract -= rem;
    }
    return decimal;
}

int main() {
    cout << 10.1_oct; //8.125
    return 0;
}

答案 2 :(得分:1)

user2079303blojayble都给出了很好的答案,但两者都有点不完整。所以这里是扩展它们和发现的其他信息。

C ++中没有八进制浮点数...原因

标准没有定义八进制浮点数,编译器遵循这个特殊的规则。前导0被读作整个部分或指数中的另一个十进制数字。

可能的原因是像0.2这样的数字含糊不清。大多数人都是这个意思⅕;而如果八进制浮点数是实际的,那么0是八进制文字(see here)的原因相同,则为1/4。

C ++中没有十六进制浮点数,但是......

...,但是在C.中有很多编译器允许使用它们,但它们有点奇怪。

首先,没有指数部分它们不起作用。所以写0x12a.b3可能不会起作用。

其次,以十六进制表示法e不是指数,因为它是数字14.因此,使用p(可能意味着“权力”)。

第三,指数十六进制不是10(当然),但它不是16(由于某种原因)。而它是2.所以0x12.4p3变为(1×16¹+ 2×16⁰+ 4×16 -1)×2³=(16 + 2 + 1/4)×8 = 146。

在C ++ 11中定义自己的文字是相对简单的

blojayble提供了自己的实现,但我认为最好将其重做为constexpr。最终结果是以下代码:

constexpr unsigned long long operator"" _oct(unsigned long long l)
{
    return
        (l < 9) ? l :
        operator"" _oct(l/10)*8 + l%10;
}
constexpr long double operator"" _oct(long double d)
{
    return
        (d == 0) ? 0.0 :
        (d < 1) ? 0.125*(((int)(d*10)) + operator"" _oct(d*10-((int)(d*10)))) :
        operator"" _oct((unsigned long long)d) + operator"" _oct(d-(unsigned long long)d);
}