|
■No85086 (ANA さん) に返信 > そのため、何かの関数のラッパーになっているのではないかと思います。 すべて何某かのラッパーではあるので、どこまでを指しているのかにもよりますが:
> Dim Num as Single = CSng("3.345235235235534543634") '14.3秒 > CType("3.345235235235534543634", Single) '14.1秒 コンパイル後は、CSng(s) と CType(s, Single) は完全に等価ですので、 この 0.2 秒の差は測定誤差ということになりますね。
> Single.Parse("3.345235235235534543634") '2.0秒 > Convert.ToSingle("3.345235235235534543634") '2.0秒 この 2 つは別のメソッド呼び出しとしてコンパイルされますが、 処理速度が変わらないのは、どちらも内部的には If value Is Nothing Then Return 0.0F Else Return Single.Parse(value, CultureInfo.CurrentCulture) End If に相当する同一の手順で処理されるためです。
一応、呼び出し回数を軽減させるために、 Dim ci As CultureInfo = CultureInfo.CurrentCulture Dim ns As NumberStyles = NumberStyles.AllowLeadingWhite Or NumberStyles.AllowTrailingWhite Or NumberStyles.AllowLeadingSign Or NumberStyles.AllowDecimalPoint Or NumberStyles.AllowThousands Or NumberStyles.AllowExponent For n = 1 To 繰り返し回数 Dim Num As Single = Single.Parse("3.345235235235534543634", ns, ci) Next とすることはできます。もっとも、軽減したとしても、微々たる差でしょうから、 可読性を落としてまで実装する価値は無さそうですけれども。
> Dim Num as Single = CSng("3.345235235235534543634") '14.3秒 > Dim Num as Single = CSng(Val("3.345235235235534543634")) '1.4秒
CSng は「現在のカルチャー」に応じてその振る舞いを変化させますが、 Val はカルチャーを考慮せず、常に同じ動作になります。 そのため、Val を使った方が処理効率が早くなっています。
しかも後者の場合、実際には「VB の CSng 関数」が呼ばれることはありません。 Val 関数の戻り値が Double 型ということで、後者は VB の CSng ではなく、 直接「MSIL の 0x6b 命令」すなわち「conv.r4」に渡される形にコンパイルされます。
しかしながら、Double 型をいったん経由することになる以上は、 必ずしも、両者の結果が同一になるとは限りません。 たとえば "-4.4E+38" という文字列を処理した場合、 前者は OverflowException を発生させますが、 後者は Single.NegativeInfinity な値として格納されます。
> このVal関数というのは、VB6以前の古いフォーマットだと思います。 > VB.NETの方法を使ったもっと美しいコードがあれば教えてください。
個人的には、Val の利用を否定はしないですけれどね。 Microsoft.VisualBasic.Compatibility.VB6 名前空間に 所属しているわけでもないですし、今回のように 明確な意図があって使っているのならなおのこと。 # 意図的に Val を選択したことについては、コメント等で触れておいて欲しいですが。
ちなみに、 ・Val では、小数点記号として "." しか認めない。CSng や Single.Parse はカルチャーを考慮する。 ・Val("123D-2") は 1.23 を返すが、CSng("123D-2") や Single.Parse("123D-2") は例外を発する。 ・全角の "(123)"を渡すと、Val は 0.0 を返し、CSngは -123.0 を返し、Single.Parse は例外を発する。 などの違いがあります。
> Dim Num as Single = CSng("3.345235235235534543634") '14.3秒 本題からは外れますが、そもそも Single 型で、 "3.3452352…" な値をとることはなかったりします。
3.345235235235534543634 を指定しても、内部値的には 3.3452353477478027343750 相当の値にしかならないためです。
ちなみに Single 精度では、下記のような非連続の近似値として格納されます。 0b01000000010101100001100001010100 → 3.3452348709106445312500 相当(3.34523487) 0b01000000010101100001100001010101 → 3.3452351093292236328125 相当(3.345235) 0b01000000010101100001100001010110 → 3.3452353477478027343750 相当(3.34523535) 0b01000000010101100001100001010111 → 3.3452355861663818359375 相当(3.34523559) 0b01000000010101100001100001011000 → 3.3452358245849609375000 相当(3.34523582)
※左がバイナリ表現(二進小数化する前の値)、右が十進小数化後の値とラウンドトリップ表現。
|