如何获取“双精度”的位数作为“长”

发布于 2024-10-08 01:33:43 字数 376 浏览 4 评论 0原文

我想在 C# 中操作浮点数的按位表示。 BinaryWriter 和 BinaryReader 这样做是这样的:

public virtual unsafe void Write(double value)
{
    ulong num = *((ulong*) &value);
    ...
}
public virtual unsafe double ReadDouble()
{
    ...
    ulong num3 = ...;
    return *((double*) &num3);
}

有没有一种方法可以在没有不安全代码的情况下做到这一点,并且没有实际使用 BinaryWriter 和 BinaryReader 的开销?

I would like to manipulate the bitwise representation of floating-point numbers in C#. BinaryWriter and BinaryReader do it this way:

public virtual unsafe void Write(double value)
{
    ulong num = *((ulong*) &value);
    ...
}
public virtual unsafe double ReadDouble()
{
    ...
    ulong num3 = ...;
    return *((double*) &num3);
}

Is there a way to do this without unsafe code, and without the overhead of actually using BinaryWriter and BinaryReader?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

耳钉梦 2024-10-15 01:33:43

另一种方法是使用具有显式布局的自定义结构,该结构在偏移量 0 处定义了 longdouble。这相当于 union

这样的东西:

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit)]
struct DoubleLongUnion
{
    [FieldOffset(0)] 
    public long Long;
    [FieldOffset(0)] 
    public double Double;
}

然后使用这个:

var union = new DoubleLongUnion();
union.Double = 1.234d;
var longBytes = union.Long;

这将避免任何不安全的代码,并且当您在堆栈上执行转换时也应该执行得相当快。

我还没有尝试/编译过这个,但我认为它应该可以工作:)

编辑

我刚刚尝试过这个并且它有效。上面的 longBytes 的值是 4608236261112822104。

一些其他值:

0d              -> 0L
double.NaN      -> -2251799813685248L
double.MinValue -> -4503599627370497L
double.MaxValue -> 9218868437227405311L

这是一个可以执行您想要的操作的方法:

public static long DoubleToLong(double d)
{
    return new DoubleLongUnion { Double = d }.Long;
}

Another way is to use a custom struct with explicit layout that defines both a long and a double at offset 0. This is equivalent to a union in C.

Something like this:

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit)]
struct DoubleLongUnion
{
    [FieldOffset(0)] 
    public long Long;
    [FieldOffset(0)] 
    public double Double;
}

Then use this:

var union = new DoubleLongUnion();
union.Double = 1.234d;
var longBytes = union.Long;

This will avoid any unsafe code and should perform pretty fast too as you perform the conversion on the stack.

I haven't tried/compiled this but I reckon it should work :)

EDIT

I just tried this and it works. The value of longBytes above is 4608236261112822104.

Some other values:

0d              -> 0L
double.NaN      -> -2251799813685248L
double.MinValue -> -4503599627370497L
double.MaxValue -> 9218868437227405311L

Here's a method that does what you want:

public static long DoubleToLong(double d)
{
    return new DoubleLongUnion { Double = d }.Long;
}
单身情人 2024-10-15 01:33:43

您是否试图完全避免不安全的代码,或者您只是想要替代 BinaryReaderBinaryWriter 上的那些特定方法?

您可以使用 BitConverter.DoubleToInt64BitsBitConverter.Int64BitsToDouble,它们旨在完全满足您的需要,尽管我认为它们在幕后使用与 BinaryReader/BinaryWriter 方法相同的不安全转换。

Are you trying to avoid unsafe code altogether, or do you just want an alternative to those specific methods on BinaryReader and BinaryWriter?

You could use BitConverter.DoubleToInt64Bits and BitConverter.Int64BitsToDouble, which are designed to do exactly what you need, although I think they use the same unsafe conversion behind-the-scenes as the BinaryReader/BinaryWriter methods.

缪败 2024-10-15 01:33:43

您可以使用 byte[] BitConverter.GetBytes(double)long BitConverter.ToInt64(byte[],int) (传递 0 作为起始索引),但是 < em>在内部 IIRC 这些使用不安全的代码,并且有数组的开销。选择你的毒药...

You can use byte[] BitConverter.GetBytes(double) and long BitConverter.ToInt64(byte[],int) (passing 0 as the start-index), but internally IIRC these use unsafe code, plus have the overhead of an array. Pick your poison...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文