C++ 获取';一';C浮点数的以2为基数表示的数字

C++ 获取';一';C浮点数的以2为基数表示的数字,c++,c,floating-point,bit-manipulation,C++,C,Floating Point,Bit Manipulation,假设我有一个浮点数。我想提取数字以2为基数表示的所有1位数的位置 例如,10.25=2^-2+2^1+2^3,所以它的基-2个一的位置是{-2,1,3} 一旦我有了一个数字的基2幂的列表n,以下应该总是返回true(在伪代码中) 但是,在C和C++中的浮点上执行位逻辑有点困难,甚至更难移植。 如何在两种语言中使用少量CPU指令实现这一点?放弃可移植性,假设IEEEfloat和32位int // Doesn't check for NaN or denormalized. // Left as a

假设我有一个浮点数。我想提取数字以2为基数表示的所有1位数的位置

例如,10.25=2^-2+2^1+2^3,所以它的基-2个一的位置是{-2,1,3}

一旦我有了一个数字的基2幂的列表
n
,以下应该总是返回true(在伪代码中)

但是,在C和C++中的浮点上执行位逻辑有点困难,甚至更难移植。
如何在两种语言中使用少量CPU指令实现这一点?

放弃可移植性,假设IEEE
float
和32位
int

// Doesn't check for NaN or denormalized.
// Left as an exercise for the reader.
void pbits(float x)
{
    union {
        float f;
        unsigned i;
    } u;
    int sign, mantissa, exponent, i;
    u.f = x;
    sign = u.i >> 31;
    exponent = ((u.i >> 23) & 255) - 127;
    mantissa = (u.i & ((1 << 23) - 1)) | (1 << 23);
    for (i = 0; i < 24; ++i) {
        if (mantissa & (1 << (23 - i)))
            printf("2^%d\n", exponent - i);
    }
}

使用
联合
的技巧不太可能产生警告或混淆编译器。

不需要使用浮点数编码。C提供以可移植方式处理浮点值的例程。下面的工作

#include <math.h>
#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{
    /*  This should be replaced with proper allocation for the floating-point
        type.
    */
    int powers[53];
    double x = atof(argv[1]);

    if (x <= 0)
    {
        fprintf(stderr, "Error, input must be positive.\n");
        return 1;
    }

    // Find value of highest bit.
    int e;
    double f = frexp(x, &e) - .5;
    powers[0] = --e;
    int p = 1;

    // Find remaining bits.
    for (; 0 != f; --e)
    {
        printf("e = %d, f = %g.\n", e, f);
        if (.5 <= f)
        {
            powers[p++] = e;
            f -= .5;
        }
        f *= 2;
    }

    // Display.
    printf("%.19g =", x);
    for (int i = 0; i < p; ++i)
        printf(" + 2**%d", powers[i]);
    printf(".\n");

    // Test.
    double y = 0;
    for (int i = 0; i < p; ++i)
        y += ldexp(1, powers[i]);

    if (x == y)
        printf("Reconstructed number equals original.\n");
    else
        printf("Reconstructed number is %.19g, but original is %.19g.\n", y, x);

    return 0;
}
#包括
#包括
#包括
int main(int argc,char*argv[])
{
/*这应该用适当的浮点分配来代替
类型。
*/
整数幂[53];
双x=atof(argv[1]);

如果(x)这不可能是可移植的,因为该标准不保证IEEE浮点值。另外,如果“一”数字超出范围?事实上,我并不介意不可移植性,只要它可以工作,比如说Linux x86_64,带有gcc和保证IEEE浮点。任何其他架构都可以使用经过调整的代码或缓慢的朴素方法。避免低级位操作的目的是什么?唯一的逻辑解决方案是使用并集将浮点转换为整数。然后提取指数并应用偏移量。如果指数为负值或>23/52,则它超出范围。不,您可以使用
frexp
,然后它变得完全可移植。在代码顶部,您将看到一条注释
//留给读者作为练习
,这非常有效。它还可以通过一系列定义进行某种程度的推广谢谢你! $ ./a.out 156 2^7 2^4 2^3 2^2 $ ./a.out 0.3333333333333333333333333 2^-2 2^-4 2^-6 2^-8 2^-10 2^-12 2^-14 2^-16 2^-18 2^-20 2^-22 2^-24 2^-25
float x = ...;
unsigned i = *(unsigned *) &x; // no
#include <math.h>
#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{
    /*  This should be replaced with proper allocation for the floating-point
        type.
    */
    int powers[53];
    double x = atof(argv[1]);

    if (x <= 0)
    {
        fprintf(stderr, "Error, input must be positive.\n");
        return 1;
    }

    // Find value of highest bit.
    int e;
    double f = frexp(x, &e) - .5;
    powers[0] = --e;
    int p = 1;

    // Find remaining bits.
    for (; 0 != f; --e)
    {
        printf("e = %d, f = %g.\n", e, f);
        if (.5 <= f)
        {
            powers[p++] = e;
            f -= .5;
        }
        f *= 2;
    }

    // Display.
    printf("%.19g =", x);
    for (int i = 0; i < p; ++i)
        printf(" + 2**%d", powers[i]);
    printf(".\n");

    // Test.
    double y = 0;
    for (int i = 0; i < p; ++i)
        y += ldexp(1, powers[i]);

    if (x == y)
        printf("Reconstructed number equals original.\n");
    else
        printf("Reconstructed number is %.19g, but original is %.19g.\n", y, x);

    return 0;
}