この文字列「1.79769313486232E+308」があり、それを.NET数値(double?)に変換しようとしていますが、以下の例外が発生しています。私はを使用してConvert.ToDouble()
います。この変換を行うための適切な方法は何ですか?
OverflowException:値がDoubleに対して大きすぎるか小さすぎる
残念ながら、この値はより大きいdouble.MaxValue
ため、例外です。
codekaizenが示唆しているように、文字列のテストをハードコーディングすることができます。そもそも文字列を生成する場合のより良い(IMO)代替手段は、「r」形式指定子を使用することです。次に、生成する文字列は代わりに「1.7976931348623157E + 308」になり、正しく解析されます。
string s = double.MaxValue.ToString("r");
double d = double.Parse(s); // No exception
明らかに、データを制御できない場合は役に立ちませんが、その場合はすでにデータが失われる可能性があることを理解する必要があります。
この問題は、文字列に変換されたことが原因である可能性がDouble.MaxValue
あり、文字列が出力されるときに、すべての桁が出力されるのではなく、丸められます。この値を解析すると、doubleがオーバーフローします。
Double.TryParse
失敗した場合に文字列「1.79769313486232E+308」を使用して同等性をチェックし、文字列Double.MaxValue
をそのまま維持する必要がある場合は、置換することで簡単に回避できます。
編集:もちろん、文字列をそのままにしておく必要がない場合は、Jonが回答で説明しているように、最初にRoundTripフォーマット指定子を使用して文字列を生成します。
試してみるdouble.Parse()
か、double.TryParse()
ではなく、Convert.ToDouble()
より良い結果が得られるかどうかはわかりません。ちなみに、指定する文字列はに等しくdouble.MaxValue
、これは(もちろん)doubleに含めることができる最大値であるため、エラーの原因である可能性があります。浮動小数点の数値型は扱いにくいので、ある種の丸めが行われ、型の境界の外に押し出されていると思います。
decimal
データ型を試すこともできます。あなたはそこで幸運があるかもしれません。
これが私が思いついたものです。JonSkeetとcodekaizenに感謝します。
private double convertToDouble(string str)
{
double dbl;
if (double.TryParse(str, out dbl))
return dbl;
if (str == "1.79769313486232E+308")
return double.MaxValue;
return double.MinValue;
}
問題と解決策を示します。
var s = double.MaxValue.ToString();
double d;
if (!double.TryParse(s, out d)) {
d = s.Equals(double.MaxValue) ? double.MaxValue : double.MinValue;
}
ここでは、さまざまなフォーマットとカルチャを表し、より寛容な、より一般的な実装を示します。
#region MatchDoubleMinMaxValuesRegex
/// <summary>
/// This regex matches strings which represents either a <see cref="double.MinValue"/> or a <see cref="double.MaxValue"/>.
/// If it is a <see cref="double.MinValue"/> then the group "isNegative" will be matched as <see cref="Group.Success"/>.
/// </summary>
private static readonly Regex MatchDoubleMinMaxValuesRegex = new Regex(
@"
^
(?>(?<isNegative>-)|\+?)
1
(?>[,.]?)
79769313486232
(?>
[eE]\+308|
0{294}(?>[,.]|$)
)
",
RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace
);
#endregion
/// <summary>
/// Converts the string representation of a number in a specified culture-specific format to its double-precision floating-point number equivalent.
/// <para>This implementation is more tolerant compared to the native double.Parse implementation:
/// strings representing <see cref="double.MinValue"/> and <see cref="double.MaxValue"/> can be parsed without <see cref="OverflowException"/>.</para>
/// </summary>
/// <param name="s">A string that contains a number to convert.</param>
/// <param name="cultureInfo">For some type conversions optional culture information that shall be used to parse the value.
/// If not specified, then the Current Culture will be used.</param>
/// <param name="numberStyles">For some type conversions optional number style configuration that shall be used to parse the value.
/// If not specified, then the default will be used.</param>
/// <returns>A double-precision floating-point number that is equivalent to the numeric value or symbol specified in <paramref name="s"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="s"/> is <c>null</c>.</exception>
/// <exception cref="FormatException"><paramref name="s"/> does not represent a number in a valid format.</exception>
/// <exception cref="OverflowException"><paramref name="s"/> represents a number that is less than <see cref="double.MinValue"/> or greater than <see cref="double.MaxValue"/>.</exception>
public static double ParseDoubleEx(string s, CultureInfo cultureInfo = null, NumberStyles? numberStyles = null)
{
// Try parse
double tempValue;
bool parseSuccess = (numberStyles != null)
? double.TryParse(s, numberStyles.Value, cultureInfo, out tempValue)
: double.TryParse(s, NumberStyles.Any, cultureInfo, out tempValue);
// If parsing failed, check for Min or Max Value (by pattern)
if (parseSuccess == false)
{
Match match = MatchDoubleMinMaxValuesRegex.Match(s);
if (match.Success == true)
tempValue = (match.Groups["isNegative"].Success == false)
? double.MaxValue
: double.MinValue;
else
throw new OverflowException("A double-precision floating-point number that is equivalent to the numeric value or symbol specified in s.");
}
return tempValue;
}
私は時々同じ番号を取得します。これが私がそれに対処した方法です。
var str = "1.79769313486232E + 308"; var dbl = double.Parse(str.Replace( "E +"、 ""));
例外が言うように、その数は2倍には大きすぎます。非常に大きな数を処理する.Netライブラリには私が知っていることは何もないので、それを処理するために多数のライブラリを見つける必要があります。