C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

バイナリエディタでDoubleを探す方法

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■82950 / inTopicNo.1)  バイナリエディタでDoubleを探す方法
  
□投稿者/ ママン (1回)-(2017/02/21(Tue) 08:05:24)

分類:[.NET 全般] 


あるバイナリファイルのどこかに
倍精度浮動小数点型(Double)で定義されたある数値が格納されているのですが
それをバイナリエディタで調べたいと考えています。

バイナリエディタだと、
バイト配列か、バイト配列を文字列に変換したものと表示されるため、

倍精度浮動小数点型(Double)で定義されたある数値を
バイト配列と文字列に変換したいのですが
VB.NETだとどのようなコードで実現可能でしょうか?

よろしくお願いいたします。

引用返信 編集キー/
■82952 / inTopicNo.2)  Re[1]: バイナリエディタでDoubleを探す方法
□投稿者/ 774RR (477回)-(2017/02/21(Tue) 09:43:57)
バイト配列化は C# なら byte[] a = BitConverter.GetBytes(1.234); とか。
# Endian 固定なのが微妙な感じ。

バイト配列の文字化という要望が何を期待しているのか、それだけの文章ではどうしてよいか不明。
ASCII 文字列化なのか CP932 なのか UTF-8 なのか UTF-16 なのか、その他なのか?
文字化できないバイトはどう処理するのか?
あたりの仕様を決めないとコードにならない。

Double の特定の値の8バイトバイナリを探すってのは結構難しいと思うぞ。
Double の exact な比較になっちゃうので。
1.000000000000 と
0.999999999999 と
1.000000000001 とは違う数値になっちゃう。
探したい数値が浮動小数点数リテラル値ならまだなんとかなりそうだけど、
数値計算の結果とかだと「厳密一致」しない可能性がある。

あと Endian の考察も必要だ。

とりあえず BitConverter の結果を検索してみるのが最初だろう。

引用返信 編集キー/
■82953 / inTopicNo.3)  Re[1]: バイナリエディタでDoubleを探す方法
□投稿者/ 魔界の仮面弁士 (1144回)-(2017/02/21(Tue) 09:46:29)
2017/02/21(Tue) 09:58:02 編集(投稿者)

No82950 (ママン さん) に返信
> バイナリエディタだと、
> バイト配列か、バイト配列を文字列に変換したものと表示されるため、
そうとも限らないでしょう。
浮動小数点検索に対応したバイナリエディタもありますよ。(TSXBINとか)


> 倍精度浮動小数点型(Double)で定義されたある数値を
> バイト配列と文字列に変換したいのですが
具体的には、どういう Double 値の時に、どういう結果にしたいのでしょうか?


バイト配列というのも、Double の生バイナリの形でよいのかどうか、
文字列と言うのも、どういう形式にするのか…。

そもそも浮動小数点は、元が二進小数な上に指数部の桁が広いので、文字列にするとなると
表現の誤差を回避するような形が求められるかと思います。たとえば、文字列と数値で
相互変換可能なラウンドトリップ書式を用いるのが良いかとは思いますが、
今回の要件が曖昧なので、それが適しているのかは判断が付かないです。
https://msdn.microsoft.com/ja-jp/library/dwhawy9k.aspx#RFormatString


> VB.NETだとどのようなコードで実現可能でしょうか?
ひとまず System.BitConverter とかは如何でしょう。


''' <summary>バイナリ検索</summary>
Iterator Function Search(ByVal source() As Byte, pattern() As Byte) As IEnumerable(Of Integer)
  Dim length As Integer = pattern.Length
  Dim i As Integer = Array.IndexOf(source, pattern(0))
  While (0 <= i AndAlso i <= (source.Length - length))
    If source.Skip(i).Take(length).SequenceEqual(pattern) Then
      Yield i
    End If
    i = Array.IndexOf(source, pattern(0), i + length)
  End While
End Function

''' <summary>Double 値を検索し、見つかった位置を返す</summary>
Function Search(ByVal source() As Byte, value As Double) As IEnumerable(Of Integer)
  Return Search(source, BitConverter.GetBytes(value))
End Function
''' <summary>Single 値を検索し、見つかった位置を返す</summary>
Function Search(ByVal source() As Byte, value As Single) As IEnumerable(Of Integer)
  Return Search(source, BitConverter.GetBytes(value))
End Function
''' <summary>文字列を検索し、見つかった位置を返す</summary>
Function Search(ByVal source() As Byte, text As String, ByVal enc As Encoding) As IEnumerable(Of Integer)
  Return Search(source, enc.GetBytes(text))
End Function
引用返信 編集キー/
■82954 / inTopicNo.4)  Re[1]: バイナリエディタでDoubleを探す方法
□投稿者/ shu (962回)-(2017/02/21(Tue) 09:47:24)
No82950 (ママン さん) に返信
>
> あるバイナリファイルのどこかに
無理です。

データフォーマットをまず特定しましょう。


引用返信 編集キー/
■82955 / inTopicNo.5)  Re[2]: バイナリエディタでDoubleを探す方法
□投稿者/ 魔界の仮面弁士 (1145回)-(2017/02/21(Tue) 11:14:29)
No82952 (774RR さん) に追記
> 1.000000000000 と
> 0.999999999999 と
> 1.000000000001 とは違う数値になっちゃう。

1.000000000001 は、内部的には (2^0 +2^-40 +2^-44 +2^-45 +2^-48 +2^-49) 相当ですね。

「^」は、VB/VBA の冪演算子。(C# だと Math.Pow)


Double バイナリを 2 進数で表記

1.000000000000 → 0 01111111111 0000000000000000000000000000000000000000000000000000
0.999999999999 → 0 01111111110 1111111111111111111111111111111111111101110011010001
1.000000000001 → 0 01111111111 0000000000000000000000000000000000000001000110011000

0.99999999999999978 → 0 01111111110 1111111111111111111111111111111111111111111111111110
0.99999999999999989 → 0 01111111110 1111111111111111111111111111111111111111111111111111
1.00000000000000000 → 0 01111111111 0000000000000000000000000000000000000000000000000000
1.00000000000000020 → 0 01111111111 0000000000000000000000000000000000000000000000000001


上記の Double バイナリを 10進小数に復元

1.000000000000 →  1.00000000000000000000000000000000000000000000000000000
0.999999999999 →  0.99999999999900002212172012150404043495655059814453125
1.000000000001 →  1.00000000000100008890058234101161360740661621093750000

0.99999999999999978 → 0.99999999999999977795539507496869191527366638183593750
0.99999999999999989 → 0.99999999999999988897769753748434595763683319091796875
1.00000000000000000 → 1.00000000000000000000000000000000000000000000000000000
1.00000000000000020 → 1.00000000000000022204460492503130808472633361816406250

引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ