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

わんくま同盟

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

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

■85915 / 3階層)  指数表記された文字列の数値変換方法について
□投稿者/ 魔界の仮面弁士 (1489回)-(2017/12/01(Fri) 11:13:23)
# 解決済みマークはつけたままにしておきます。

No85904 (たかじ さん) に返信
>>> 指数表記されている文字列(2.12345678975E9や3.4E+38など)を
>>> decimalにTryParseすると、変換に失敗します。
>> 後者はどうやっても不可能です。最大値(decimal.MaxValue)を大幅に超えていますから…。
> 3.4E+38の変換については、型の問題もありますので、解決方法検討してみます。


値が大きいので、基本的には System.Single や System.Double の
出番な気がしますが、最終的には要件が求める許容誤差次第ですね。


あとは System.Numerics.BigInteger を使う手もありますが、
あくまで整数なので、"3.4E+38" はパースできても、
"2.12345678975E9" の方には使えません。


using System;
using System.Globalization;
using System.Numerics; // 参照設定: System.Numerics.dll
class Program
{
 static void Main()
 {
  var ns = NumberStyles.Float;
  var fmt = CultureInfo.InvariantCulture;

  string s1 = "2.12345678975E9";
  decimal dm; double d1; float f1;
  decimal.TryParse(s1, ns, fmt, out dm); // true
  double.TryParse(s1, ns, fmt, out d1);  // true
  float.TryParse(s1, ns, fmt, out f1);  // true
  Console.WriteLine("{0:N4}", dm); // 2,123,456,789.7500
  Console.WriteLine("{0:N4}", d1); // 2,123,456,789.7500
  Console.WriteLine("{0:N4}", f1); // 2,123,457,000.0000

  string s2 = "3.4E+38";
  BigInteger b1, b2, b3; double d2; float f2;
  BigInteger.TryParse(s2, ns, fmt, out b1); // true
  double.TryParse(s2, ns, fmt, out d2);   // true
  float.TryParse(s2, ns, fmt, out f2);    // true
  b2 = (BigInteger)d2;
  b3 = (BigInteger)f2;
  Console.WriteLine("{0:N4}", b1); // 340,000,000,000,000,000,000,000,000,000,000,000,000.0000
  Console.WriteLine("{0:N4}", d2); // 340,000,000,000,000,000,000,000,000,000,000,000,000.0000
  Console.WriteLine("{0:N4}", b2); // 339,999,999,999,999,996,123,846,586,046,231,871,488.0000
  Console.WriteLine("{0:N4}", b3); // 339,999,995,214,436,424,907,732,413,799,364,296,704.0000

  Console.ReadKey();
 }
}


あとは、nuget などからの導入になりますが、BigDecimal とかですかね。


Deveel.Math.BigDecimal v1, v2, v3;
Deveel.Math.BigDecimal.TryParse("2.12345678975E9", out v1);
Deveel.Math.BigDecimal.TryParse("3.4E+38", out v2);
Deveel.Math.BigDecimal.TryParse("340000000000000000000000000000000000000", out v3);

上記はいずれも true を返しますが、値の大小比較をする際には注意が必要です。
v2 と v3 は、数値的には同じ値ですが、有効桁数が異なりますので。

Console.WriteLine(v2.CompareTo(v3)); // 0 (一致)
Console.WriteLine(v2 == v3);  // False (不一致)
Console.WriteLine("{0}", v1); // 2123456789.75
Console.WriteLine("{0}", v2); // 3.4E+38
Console.WriteLine("{0}", v3); // 340000000000000000000000000000000000000

※ v2 は 指数 -37、有効桁数 2 桁 ( 34 × 10 ^ -37)
※ v3 は 指数 0、有効桁数 39 桁 (340000000000000000000000000000000000000 × 10 ^ 0)
解決済み
編集キー/

前の記事(元になった記事) 次の記事(この記事の返信)
←Re[2]: 指数表記された文字列の数値変換方法について /たかじ →Re[4]: 指数表記された文字列の数値変換方法について /たかじ
 
上記関連ツリー

指数表記された文字列の数値変換方法について / たかじ (17/11/28(Tue) 17:28) #85832
Re[1]: 指数表記された文字列の数値変換方法について / WebSurfer (17/11/28(Tue) 18:07) #85833
Re[1]: 指数表記された文字列の数値変換方法について / 魔界の仮面弁士 (17/11/29(Wed) 09:42) #85853
  └ Re[2]: 指数表記された文字列の数値変換方法について / たかじ (17/11/30(Thu) 16:33) #85904 解決済み
    └ 指数表記された文字列の数値変換方法について / 魔界の仮面弁士 (17/12/01(Fri) 11:13) #85915 解決済み ←Now
      └ Re[4]: 指数表記された文字列の数値変換方法について / たかじ (17/12/06(Wed) 10:14) #85967
        ├ Re[5]: 指数表記された文字列の数値変換方法について / 魔界の仮面弁士 (17/12/06(Wed) 13:31) #85971
        └ Re[5]: 指数表記された文字列の数値変換方法について / Hongliang (17/12/06(Wed) 11:59) #85970
          └ Re[6]: 指数表記された文字列の数値変換方法について / 魔界の仮面弁士 (17/12/06(Wed) 14:16) #85972
            └ Re[7]: 指数表記された文字列の数値変換方法について / たかじ (17/12/07(Thu) 19:00) #85999 解決済み

上記ツリーを一括表示 / 上記ツリーをトピック表示
 
上記の記事へ返信