2009/11/01

C#で浮動小数点数のバイナリ表現(ビットパターン)を取得する

double型の値のバイト表現をlong型で得るために、BitConverter.DoubleToInt64Bitsを使う場合とunsafeで無理やりキャストするのではどちらが速いのか比較してみた。
手元の環境ではBitConverter.DoubleToInt64Bitsの方が速かった(経過時間が50%)けど、ほとんどのケースでは相対的に十分軽い処理になるだろうからどっちでもいい。ただキャストを使うやり方はunsafeの指定が必要だし、見た目もアレだからfloat型を相手にする場合以外は使わないと思う(BitConverter.FloatToInt32Bitsは存在しない)。ストップウォッチのリセットを忘れてた。処理速度に差はない。
そもそもdouble型と整数型との&演算子があればこんなことしなくていいのが残念。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace BinaryRepresentation
{
    class Program
    {
        static void Main(string[] args)
        {
            var sw = new Stopwatch();
            var random = new Random(0);
            var num = 1000000;
            var vals = new double[num];
            for (var n = 0; n < vals.Length; n++)
                vals[n] = random.NextDouble();

            // BitConverter.DoubleToInt64Bits
            var bc = new long[vals.Length];
            {
                sw.Reset();
                sw.Start();
                for (var n = 0; n < vals.Length; n++)
                    bc[n] = BitConverter.DoubleToInt64Bits(vals[n]);
                sw.Stop();
                Console.WriteLine("BitConverter.DoubleToInt64Bits: {0}", sw.ElapsedMilliseconds);
            }

            // unsafe cast
            var uc = new long[vals.Length];
            unsafe
            {
                sw.Reset();
                sw.Start();
                for (var n = 0; n < vals.Length; n++)
                {
                    var val = vals[n];
                    uc[n] = *(long*)&val;
                }
                sw.Stop();
                Console.WriteLine("unsafe cast: {0}", sw.ElapsedMilliseconds);
            }

            // correctness
            for (var n = 0; n < vals.Length; n++)
                if (bc[n] != uc[n])
                    Console.WriteLine("bc[{0}]: {1:X}, uc[{0}]: {2:X}", n, bc[n], uc[n]);
        }
    }
}
ksksts / junk / source — bitbucket.org

0 件のコメント: