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

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

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.91729 の関連記事表示

<< 0 >>
■91729  長い桁数の定数を使用する方法
□投稿者/ kozue -(2019/07/26(Fri) 12:41:48)

    分類:[.NET 全般] 


    例えば、
    Dim kbs As Single = 3.14159265358979312384626433
    Dim kbd As Double = 3.14159265358979312384626433

    というコードをコピペで貼り付けても
    桁数が丸められて以下のようになってしまいます。

    Dim kbs As Single = 3.1415926535897931
    Dim kbd As Double = 3.1415926535897931
    SingleでもDoubleでも有効数字が変わらないのはなぜなのでしょうか?

    どうすれば、もっと長い桁数の定数を使用することができますか?
親記事 /過去ログ158より / 関連記事表示
削除チェック/

■91730  Re[1]: 長い桁数の定数を使用する方法
□投稿者/ KOZ -(2019/07/26(Fri) 13:10:20)
    No91729 (kozue さん) に返信
    > Dim kbs As Single = 3.1415926535897931
    > Dim kbd As Double = 3.1415926535897931
    > SingleでもDoubleでも有効数字が変わらないのはなぜなのでしょうか?

    それぞれ ToString() してみると

    Debug.Print(kbs.ToString("G28"))
    Debug.Print(kbd.ToString("G28"))
    3.14159274
    3.1415926535897931

    有効桁は違います。

    > どうすれば、もっと長い桁数の定数を使用することができますか?

    そのような型を定義します。
    たとえば、ODP.NET の OracleDecimal 構造体は 38 桁まで扱えるので

    Dim od1 As New OracleDecimal("3.14159265358979312384626433")
    Dim od2 As New OracleDecimal("3.14159265358979312384626433")
    Dim od3 As OracleDecimal = od1 + od2
    Debug.Print("{0}", od3.ToString())

    結果:
    6.28318530717958624769252866

    と、キレイに計算できます。

記事No.91729 のレス /過去ログ158より / 関連記事表示
削除チェック/

■91731  Re[2]: 長い桁数の定数を使用する方法
□投稿者/ KOZ -(2019/07/26(Fri) 13:29:16)
    System.Data.SqlTypes 名前空間の SqlDecimal でもいけました。

    Dim sd1 As SqlDecimal = SqlDecimal.Parse("3.14159265358979312384626433")
    Dim sd2 As SqlDecimal = SqlDecimal.Parse("3.14159265358979312384626433")
    Dim sd3 As SqlDecimal = sd1 + sd2
    Debug.Print("{0}", sd3.ToString())

    結果:
    6.28318530717958624769252866
記事No.91729 のレス /過去ログ158より / 関連記事表示
削除チェック/

■91732  Re[3]: 長い桁数の定数を使用する方法
□投稿者/ kozue -(2019/07/26(Fri) 13:38:12)
    ありがとうございます。

    singleとdoubleの桁数を勘違いしていました。

    ちなみに
    https://www.cc.kyoto-su.ac.jp/~yamada/programming/float.html
    Singleは7桁doubleは15桁と書かれてありますが。
    3.14159274
    3.1415926535897931

    はそれぞれ9桁と17桁になっています
    なぜこのような違い見られるのでしょうか?
記事No.91729 のレス /過去ログ158より / 関連記事表示
削除チェック/

■91735  Re[4]: 長い桁数の定数を使用する方法
□投稿者/ 魔界の仮面弁士 -(2019/07/26(Fri) 14:16:53)
    No91732 (kozue さん) に返信
    > https://www.cc.kyoto-su.ac.jp/~yamada/programming/float.html
    > Singleは7桁doubleは15桁と書かれてありますが。
    > 3.14159274
    > 3.1415926535897931
    > はそれぞれ9桁と17桁になっています
    ラウンドトリップ文字列と「有効桁数」は別物ですよ。

    > なぜこのような違い見られるのでしょうか?
    Decimal 型が、その名前の通り「10進数」相当の管理を行っているのに対して、
    Single や Double は「2 進数」管理の小数であることはご存知でしょうか。

    Single の有効桁数は、2 進表現で 23+1 桁なので、
    10 進表現では「7.2247198959…桁」にあたります。

    Double の有効桁数は、2 進表現で 52+1 桁なので、
    10 進表現では「15.954589770…桁」にあたります。


    > 3.14159274
    Single の 3.14159274 は、内部的には
     0b0_10000000_10010010000111111101000
    に相当するバイナリとして保持されています。
    これは 10 進数では 3.1415958404541015625 相当の値です。

    要するに、
     (2^1 +2^0 +2^-3 +2^-6 +2^-11 +2^-12 +2^-13 +2^-14 +2^-15 +2^-16 +2^-17 +2^-19)
    ということです。

    バイナリの 0b0_10000000_10010010000111111101000 を
    1 増やして 0b0_10000000_10010010000111111101001 にすると、
    10 進数で 3.1415960788726806640625 相当になります。

    1 減らして 0b0_10000000_10010010000111111100111 にすると、
    10 進数で 3.1415956020355224609375 相当です。

    これら隣り合う三つの値を並べてみると、
     3.1415956020355224609375
     3.1415958404541015625
     3.1415960788726806640625
    となりますよね。なので、元データの有効桁数が 24 bit あっても、
    10進小数としてラウンドトリップする場合、この数値域においては
     3.14159274
    の桁数まであれば、十分に元の Single 値を表現できるというわけです。
記事No.91729 のレス /過去ログ158より / 関連記事表示
削除チェック/

■91737  Re[5]: 長い桁数の定数を使用する方法
□投稿者/ KOZ -(2019/07/26(Fri) 14:34:49)
    No91735 (魔界の仮面弁士 さん) に返信

    フォローありがとうございます。
    こういうのがサクっと書けるのは流石。

    元ネタですが Decimal でOKでした・・・

    Dim dec As Decimal = 3.14159265358979312384626433D
記事No.91729 のレス /過去ログ158より / 関連記事表示
削除チェック/

■91736  Re[4]: 長い桁数の定数を使用する方法
□投稿者/ 魔界の仮面弁士 -(2019/07/26(Fri) 14:28:09)
    No91732 (kozue さん) に返信
    > 3.1415926535897931
    ついでに Double の近似値についても。

    上記は 0b0_10000000000_1001001000011111101101010100010001000010110100011000 であり、

    = (2^1 +2^0 +2^-3 +2^-6 +2^-11 +2^-12 +2^-13 +2^-14 +2^-15
    +2^-16 +2^-17 +2^-20 +2^-21 +2^-22 +2^-23 +2^-26 +2^-28
    +2^-33 +2^-37 +2^-38 +2^-40 +2^-41 +2^-45 +2^-46 +2^-51)

    相当なので、そのまま復元すると、
     3.141595740000000080982545114238746464252471923828125
    に相当します。


    内部バイナリを 1 bit ずつずらして近似値を作ると
     -2: 0b0_10000000000_1001001000011111101101010100010001000010110100010110
     -1: 0b0_10000000000_1001001000011111101101010100010001000010110100010111
     =0: 0b0_10000000000_1001001000011111101101010100010001000010110100011000
     +1: 0b0_10000000000_1001001000011111101101010100010001000010110100011001
     +2: 0b0_10000000000_1001001000011111101101010100010001000010110100011010
    になるので、これを 10 進小数に戻すと
     -2: 3.14159265358979222781954376841895282268524169921875
     -1: 3.141592653589792671908753618481568992137908935546875
     =0: 3.141592653589793115997963468544185161590576171875
     +1: 3.141592653589793560087173318606801331043243408203125
     +2: 3.14159265358979400417638316866941750049591064453125
    になります。

    なので、実運用上の表現形式では
     =0: 3.1415926535897931
    の桁数まで表現すれば、前後の近似値と区別できますね。
記事No.91729 のレス /過去ログ158より / 関連記事表示
削除チェック/

■91738  Re[1]: 長い桁数の定数を使用する方法
□投稿者/ 魔界の仮面弁士 -(2019/07/26(Fri) 15:00:20)
    No91729 (kozue さん) に返信
    >  Dim kbs As Single = 3.14159265358979312384626433
    >  Dim kbd As Double = 3.14159265358979312384626433

    「3.14159265358979312384626433」表記だと、Double 型と認識されます。
    https://docs.microsoft.com/ja-jp/dotnet/visual-basic/programming-guide/language-features/data-types/type-characters


    型を明示するには、
     Dim sng1 As Single = 3.14159265358979312384626433F
     Dim sng2 As Single = 3.14159265358979312384626433!

     Dim dbl1 As Double = 3.14159265358979312384626433R
     Dim dbl2 As Double = 3.14159265358979312384626433#

     Dim dec1 As Decimal= 3.14159265358979312384626433D
     Dim dec2 As Decimal= 3.14159265358979312384626433@
    のようにします。


    ただし、表現しきれない桁部分は自動的に削がれるので、上記が
     Dim sng1 As Single = 3.14159274F
     Dim sng2 As Single = 3.14159274!

     Dim dbl1 As Double = 3.1415926535897931R
     Dim dbl2 As Double = 3.1415926535897931#

     Dim dec1 As Decimal = 3.14159265358979312384626433D
     Dim dec2 As Decimal = 3.14159265358979312384626433@
    などに書き換わる点については変わりありません。
記事No.91729 のレス /過去ログ158より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -