Language agnostic 如何显示浮点或双精度的二进制表示?

Language agnostic 如何显示浮点或双精度的二进制表示?,language-agnostic,floating-point,Language Agnostic,Floating Point,我想显示浮点数的二进制(或十六进制)表示形式。我知道如何手动转换(使用该方法),但我感兴趣的是看到同样的代码示例 虽然我特别喜欢C++和java解决方案,但我想知道是否有任何语言使它特别容易,所以我正在制作这个“强”语言不可知论< >。我想看看其他语言的解决方案 < > >编辑:我已经获得了C++、C++、C和java的良好覆盖。有没有其他的语言大师想要加入这个列表?C/C++很容易 union ufloat { float f; unsigned u; }; ufloat u1;

我想显示浮点数的二进制(或十六进制)表示形式。我知道如何手动转换(使用该方法),但我感兴趣的是看到同样的代码示例

虽然我特别喜欢C++和java解决方案,但我想知道是否有任何语言使它特别容易,所以我正在制作这个“强”语言不可知论< <强> >。我想看看其他语言的解决方案

< > >编辑:我已经获得了C++、C++、C和java的良好覆盖。有没有其他的语言大师想要加入这个列表?

C/C++很容易

union ufloat {
  float f;
  unsigned u;
};

ufloat u1;
u1.f = 0.3f;
然后您只需输出
u1.u
。你可以适应

双打同样容易

union udouble {
  double d;
  unsigned long u;
}
因为双精度是64位的


Java更容易一点:使用combined with和combined with。

Java:google搜索在

具体地说(我自己没有试过)

long binary=Double.Double-tolongbits(3.14159);
字符串strBinary=Long.toBinaryString(二进制);
在.NET(包括C#)中,您拥有接受多种类型的
位转换器,允许访问原始二进制文件;要获得十六进制数,
ToString(“x2”)
是最常见的选项(可能包装在实用方法中):

奇怪的是,base-64有一个单线转换(
Convert.ToBase64String
),但是base-16需要更多的努力。除非您参考Microsoft.VisualBasic,否则在这种情况下:

long tmp = BitConverter.DoubleToInt64Bits(123.45);
string hex = Microsoft.VisualBasic.Conversion.Hex(tmp);

Float和Double类(在Java中)都有一个toHexString('Float')方法,所以这对于十六进制转换来说非常有用

Double.toHexString(42344);
Float.toHexString(42344);

容易极了
template <class T>
std::bitset<sizeof(T)*8> binary_representation(const T& f)
{
   typedef unsigned long TempType;
   assert(sizeof(T)<=sizeof(TempType));
   return std::bitset<sizeof(T)*8>(*(reinterpret_cast<const TempType*>(&f)));
}
/*
@(#)File:           $RCSfile: dumpdblflt.c,v $
@(#)Version:        $Revision: 1.1 $
@(#)Last changed:   $Date: 2007/09/05 22:23:33 $
@(#)Purpose:        Print C double and float data in bytes etc.
@(#)Author:         J Leffler
@(#)Copyright:      (C) JLSS 2007
@(#)Product:        :PRODUCT:
*/

/*TABSTOP=4*/

#include <stdio.h>
#include "imageprt.h"

#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
extern const char jlss_id_dumpdblflt_c[];
const char jlss_id_dumpdblflt_c[] = "@(#)$Id: dumpdblflt.c,v 1.1 2007/09/05 22:23:33 jleffler Exp $";
#endif /* lint */

union u_double
{
    double  dbl;
    char    data[sizeof(double)];
};

union u_float
{
    float   flt;
    char    data[sizeof(float)];
};

static void dump_float(union u_float f)
{
    int exp;
    long mant;

    printf("32-bit float: sign: %d, ", (f.data[0] & 0x80) >> 7);
    exp = ((f.data[0] & 0x7F) << 1) | ((f.data[1] & 0x80) >> 7);
    printf("expt: %4d (unbiassed %5d), ", exp, exp - 127);
    mant = ((((f.data[1] & 0x7F) << 8) | (f.data[2] & 0xFF)) << 8) | (f.data[3] & 0xFF);
    printf("mant: %16ld (0x%06lX)\n", mant, mant);
}

static void dump_double(union u_double d)
{
    int exp;
    long long mant;

    printf("64-bit float: sign: %d, ", (d.data[0] & 0x80) >> 7);
    exp = ((d.data[0] & 0x7F) << 4) | ((d.data[1] & 0xF0) >> 4);
    printf("expt: %4d (unbiassed %5d), ", exp, exp - 1023);
    mant = ((((d.data[1] & 0x0F) << 8) | (d.data[2] & 0xFF)) << 8) |
              (d.data[3] & 0xFF);
    mant = (mant << 32) | ((((((d.data[4] & 0xFF) << 8) |
              (d.data[5] & 0xFF)) << 8) | (d.data[6] & 0xFF)) << 8) |
              (d.data[7] & 0xFF);
    printf("mant: %16lld (0x%013llX)\n", mant, mant);
}

static void print_value(double v)
{
    union u_double d;
    union u_float  f;

    f.flt = v;
    d.dbl = v;

    printf("SPARC: float/double of %g\n", v);
    image_print(stdout, 0, f.data, sizeof(f.data));
    image_print(stdout, 0, d.data, sizeof(d.data));
    dump_float(f);
    dump_double(d);
}


int main(void)
{
    print_value(+1.0);
    print_value(+2.0);
    print_value(+3.0);
    print_value( 0.0);
    print_value(-3.0);
    print_value(+3.1415926535897932);
    print_value(+1e126);
    return(0);
}
模板
std::位集二进制表示(常量T&f)
{
typedef无符号长类型;
assert(sizeof(T)我是这样做的:

template <class T>
std::bitset<sizeof(T)*8> binary_representation(const T& f)
{
   typedef unsigned long TempType;
   assert(sizeof(T)<=sizeof(TempType));
   return std::bitset<sizeof(T)*8>(*(reinterpret_cast<const TempType*>(&f)));
}
/*
@(#)File:           $RCSfile: dumpdblflt.c,v $
@(#)Version:        $Revision: 1.1 $
@(#)Last changed:   $Date: 2007/09/05 22:23:33 $
@(#)Purpose:        Print C double and float data in bytes etc.
@(#)Author:         J Leffler
@(#)Copyright:      (C) JLSS 2007
@(#)Product:        :PRODUCT:
*/

/*TABSTOP=4*/

#include <stdio.h>
#include "imageprt.h"

#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
extern const char jlss_id_dumpdblflt_c[];
const char jlss_id_dumpdblflt_c[] = "@(#)$Id: dumpdblflt.c,v 1.1 2007/09/05 22:23:33 jleffler Exp $";
#endif /* lint */

union u_double
{
    double  dbl;
    char    data[sizeof(double)];
};

union u_float
{
    float   flt;
    char    data[sizeof(float)];
};

static void dump_float(union u_float f)
{
    int exp;
    long mant;

    printf("32-bit float: sign: %d, ", (f.data[0] & 0x80) >> 7);
    exp = ((f.data[0] & 0x7F) << 1) | ((f.data[1] & 0x80) >> 7);
    printf("expt: %4d (unbiassed %5d), ", exp, exp - 127);
    mant = ((((f.data[1] & 0x7F) << 8) | (f.data[2] & 0xFF)) << 8) | (f.data[3] & 0xFF);
    printf("mant: %16ld (0x%06lX)\n", mant, mant);
}

static void dump_double(union u_double d)
{
    int exp;
    long long mant;

    printf("64-bit float: sign: %d, ", (d.data[0] & 0x80) >> 7);
    exp = ((d.data[0] & 0x7F) << 4) | ((d.data[1] & 0xF0) >> 4);
    printf("expt: %4d (unbiassed %5d), ", exp, exp - 1023);
    mant = ((((d.data[1] & 0x0F) << 8) | (d.data[2] & 0xFF)) << 8) |
              (d.data[3] & 0xFF);
    mant = (mant << 32) | ((((((d.data[4] & 0xFF) << 8) |
              (d.data[5] & 0xFF)) << 8) | (d.data[6] & 0xFF)) << 8) |
              (d.data[7] & 0xFF);
    printf("mant: %16lld (0x%013llX)\n", mant, mant);
}

static void print_value(double v)
{
    union u_double d;
    union u_float  f;

    f.flt = v;
    d.dbl = v;

    printf("SPARC: float/double of %g\n", v);
    image_print(stdout, 0, f.data, sizeof(f.data));
    image_print(stdout, 0, d.data, sizeof(d.data));
    dump_float(f);
    dump_double(d);
}


int main(void)
{
    print_value(+1.0);
    print_value(+2.0);
    print_value(+3.0);
    print_value( 0.0);
    print_value(-3.0);
    print_value(+3.1415926535897932);
    print_value(+1e126);
    return(0);
}

我不得不考虑在这里发布一段时间,因为这可能会激励其他程序员使用C做坏事。我决定无论如何发布它,但请记住:在没有适当文档的情况下,不要将这种代码编写到任何严肃的应用程序中,甚至要三思而后行

撇开免责声明不谈,我们开始吧

首先编写一个函数,用于以二进制格式打印长无符号变量:

void printbin(unsigned long x, int n)
{
  if (--n) printbin(x>>1, n);
  putchar("01"[x&1]);
}
不幸的是,我们不能直接使用这个函数来打印我们的浮点变量,所以我们必须进行一些修改。阅读过《地震的诀窍》的人可能都很熟悉这种修改。我们的想法是为我们的浮点变量设置一个值,然后为我们的长整型变量获得相同的位掩码。因此,我们取内存地址f,convert将其转换为长*值,并使用该指针将f的位掩码作为长无符号。如果将此值打印为长无符号,结果将是一团混乱,但位与原始浮点值中的位相同,因此这并不重要

int main(void)
{
  long unsigned lu;
  float f = -1.1f;

  lu = *(long*)&f;
  printbin(lu, 32);
  printf("\n");
  return 0;
}

如果您认为这种语法很糟糕,那么您是对的。

在Haskell中,没有可访问的浮点的内部表示形式。但是您可以从多种格式(包括Float和Double)进行二进制序列化。以下解决方案对于具有数据实例的任何类型都是通用的。二进制支持:

module BinarySerial where

import Data.Bits
import Data.Binary
import qualified Data.ByteString.Lazy as B

elemToBits :: (Bits a) => a -> [Bool]
elemToBits a = map (testBit a) [0..7]

listToBits :: (Bits a) => [a] -> [Bool]
listToBits a = reverse $ concat $ map elemToBits a

rawBits :: (Binary a) => a -> [Bool]
rawBits a = listToBits $ B.unpack $ encode a
可以使用原始位进行转换:

rawBits (3.14::Float)
但是,如果需要以这种方式访问浮点值,则可能是做错了什么。真正的问题可能是如何访问浮点数的指数和有效位?答案是Prelude中的和有效位:

significand 3.14
0.785

exponent 3.14
2
在C中:

&floatVar
将获取地址内存,然后
(int*)
将是指向该地址内存的指针,最后是*以获取int中4个字节的浮点值。
然后,您可以打印二进制格式或十六进制格式。

您可以使用C#中的此类代码轻松地将浮点变量转换为int变量(或双精度转换为长):


Python:

代码:

样本:

>>> float2bin(1.0)
'0011111111110000000000000000000000000000000000000000000000000000'
>>> float2bin(-1.0)
'1011111111110000000000000000000000000000000000000000000000000000'
>>> float2bin(1.0, True)
'3ff0000000000000'
>>> float2bin(1.0, True, True)
'3f800000'
>>> float2bin(-1.0, True)
'bff0000000000000'

显然,没有人愿意提及获得十六进制指数表示法是多么微不足道,因此:

#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    // C++11 manipulator
    cout << 23.0f << " : " << std::hexfloat << 23.0f << endl;
    // C equivalent solution
    printf("23.0 in hexadecimal is: %A\n", 23.0f);
}
#包括
#包括
使用名称空间std;
int main()
{
//C++11机械手

CUT< P>为将来参考,C++ 2A引入了一个新的函数模板<代码> BITICAST CAST//COD>执行该工作。
template< class To, class From >
constexpr To bit_cast(const From& from) noexcept;
template
constexpr到bit_cast(const From和From)无异常;
我们可以简单地说

float f = 3.14;
std::bit_cast<int>(f);
float f=3.14;
标准::钻头铸件(f);

有关更多详细信息,请参见

Mind!浮点和双精度浮点的位大小是标准化的,long、int等的大小…取决于体系结构!您可以使用特定于实现的类型\uuuu int64和\uu int32(在windows上)。您可以使用my。然后您可以使用Integer::类型是整数类型。我写的是因为D FAQ声称C++不能这样做(找到一个至少有N位的类型)。代码非常保守地假设类型的大小(如果您使用“长长”),它将在所有实现中工作。。我想人们可以编写一个更好的版本,列出每种基本类型的实际大小,并根据这些事实做出决定。大多数64位系统都有64位长的类型。这是未定义的行为。不允许无序访问联合体。@KerrekSB:这个问题被标记为语言不可知,以及是否访问除定义的最后一个存储成员依赖于语言。在C中,行为是为某些类型定义的,实现是为其他类型定义的(包括使用大小相同或更小的无符号整数访问存储的double)在某些情况下,我有了不确定的行为。我在寻找问题之前,在C++中搜索了谷歌。我应该也应该寻找java解决方案。))我希望<代码> STRBION.LIFTHOST()/CUT>为64,但我得到63。有人知道为什么吗?同样,<代码>整数。(Float.floatToIntBits(floatNumber));
将返回浮点数的字符串位表示形式。这非常好。
#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    // C++11 manipulator
    cout << 23.0f << " : " << std::hexfloat << 23.0f << endl;
    // C equivalent solution
    printf("23.0 in hexadecimal is: %A\n", 23.0f);
}
template< class To, class From >
constexpr To bit_cast(const From& from) noexcept;
float f = 3.14;
std::bit_cast<int>(f);