C# 在没有溢出异常的情况下将“1.79769313486232E+308”转换为双倍?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/766918/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert "1.79769313486232E+308" to double without OverflowException?
提问by Eric Schoonover
I have this string "1.79769313486232E+308" and am trying to convert it to a .NET numeric value (double?) but am getting the below exception. I am using Convert.ToDouble()
. What is the proper way to do this conversion?
我有这个字符串“1.79769313486232E+308”,我正在尝试将其转换为 .NET 数值(double?),但出现以下异常。我正在使用Convert.ToDouble()
. 进行这种转换的正确方法是什么?
OverflowException: Value was either too large or too small for a Double
溢出异常:值对于 Double 来说太大或太小
采纳答案by codekaizen
The problem is likely due to the fact that Double.MaxValue
was converted to a string, and when the string is output, not all the digits are output, instead it is rounded. Parsing this value overflows the double.
问题很可能是由于Double.MaxValue
转换为字符串,并且在输出字符串时,并非所有数字都输出,而是四舍五入。解析此值会溢出双精度值。
Using Double.TryParse
and subsequently checking equality on the string "1.79769313486232E+308" in case of failure and substituting Double.MaxValue
should be a quick workaround, if you need to keep the string the way it is.
使用Double.TryParse
并随后检查字符串“1.79769313486232E+308”上的相等性,以防万一失败并替换Double.MaxValue
应该是一个快速的解决方法,如果您需要保持字符串的原样。
EDIT: Of course, if you don't need to keep the string the way it is, use the Round Trip format specifierto produce the string in the first place, as Jon describes in his answer.
编辑:当然,如果您不需要按原样保留字符串,请首先使用Round Trip 格式说明符生成字符串,如Jon 在他的回答中所述。
回答by Adam Robinson
You may try double.Parse()
or double.TryParse()
rather than Convert.ToDouble()
, but I'm not certain you'll get better results. Incidentally, the string that you provide is equal to double.MaxValue
, which is (of course) the maximum value that can be contained in a double, so that's likely where your error is coming from. Floating-point numeric types are finicky, so I would assume that some sort of rounding is taking place and pushing it outside the bounds of the type.
您可以尝试double.Parse()
或double.TryParse()
而不是Convert.ToDouble()
,但我不确定您会获得更好的结果。顺便说一句,您提供的字符串等于double.MaxValue
,这是(当然)可以包含在双精度中的最大值,因此这可能是您的错误的来源。浮点数字类型很挑剔,所以我假设某种舍入正在发生并将它推到类型的范围之外。
You could also try the decimal
data type. You may have better luck there.
您也可以尝试使用decimal
数据类型。你在那里可能会有更好的运气。
回答by Jamie Penney
That number is too big for a double, as the exception says. You are going to have to find a large number library to handle that for you, as there is nothing that I know of in the .Net library that handles very large numbers.
正如例外所说,这个数字对于双倍来说太大了。你将不得不找到一个大数字库来为你处理这个问题,因为在处理非常大数字的 .Net 库中我不知道什么。
回答by Jon Skeet
Unfortunately this value is greater than double.MaxValue
, hence the exception.
不幸的是,这个值大于double.MaxValue
,因此例外。
As codekaizen suggests, you could hard-code a test for the string. A better (IMO) alternative if you're the one producingthe string in the first place is to use the "r" format specifier. Then the string you produce will be "1.7976931348623157E+308" instead, which then parses correctly:
正如 codekaizen 所建议的那样,您可以对字符串进行硬编码。如果您是首先生成字符串的人,则更好的(IMO)替代方法是使用“r”格式说明符。那么你产生的字符串将是“1.7976931348623157E+308”,然后正确解析:
string s = double.MaxValue.ToString("r");
double d = double.Parse(s); // No exception
Obviously that's no help if you don't have control over the data - but then you should understand you're likely to be losing data already in that case.
显然,如果您无法控制数据,那将无济于事 - 但是您应该明白在这种情况下您可能已经丢失了数据。
回答by Eric Schoonover
Here is what I came up with. Thanks Jon Skeet and codekaizen.
这是我想出的。感谢 Jon Skeet 和 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;
}
回答by Corey Alix
Demonstrates the issue and a solution:
演示问题和解决方案:
var s = double.MaxValue.ToString();
double d;
if (!double.TryParse(s, out d)) {
d = s.Equals(double.MaxValue) ? double.MaxValue : double.MinValue;
}
回答by rittergig
Here a more generic implementation which representing different formatting and cultures and is more tolerant:
这是一个更通用的实现,它代表不同的格式和文化,并且更宽容:
#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;
}