Reputation: 295
I have tried to parse the maxvalue of long and ulong but it fails. How to do that?
Int64.TryParse(value.ToString(), out resultInt)
value
is Int64.MaxValue but the type of the value
is double.
Upvotes: 0
Views: 1254
Reputation: 35037
Since double
has the precision of ~15-17 digits it's not possible to stringify a double
that was assigned Int64.MaxValue
in a way that the string would represent exactly 9223372036854775807
(Int64.MaxValue
, 19 digits).
Int64
Don't store integral values as double
.
var l1 = long.MaxValue;
var l2 = long.Parse(l1.ToString());
Console.WriteLine( $"Diff: {l2-l1}");
// Diff: 0
With ToString("F0")
(and few other formats) it's possible to get quite close; just 1 above Int64.MaxValue
(9223372036854775808
).
You could try to trim the double string.
public static (long L, bool IsHack) GetLongUpToMaxValue(string str) {
try
{
return (long.Parse(str, NumberStyles.Any), false);
}
catch( OverflowException )
{
var ul = ulong.Parse(str, NumberStyles.Any);
if((ul - long.MaxValue) == 1) return (long.MaxValue, true);
throw;
}
}
public static void Main(string[] args)
{
Console.WriteLine($"{"SRC", -25}{"STR", -25}{"DIFF", -10}{"HACK?", -10}");
foreach(long l in new[]{Int64.MaxValue, Int64.MaxValue-1, Int64.MaxValue-2, Int64.MaxValue-100, Int64.MaxValue-1000, Int64.MinValue, Int64.MinValue+1, Int64.MinValue+2, 1000, -1000, 0})
{
double d = l;
var dStr = d.ToString("F0");// F,G19
(long l2, bool isHack) = GetLongUpToMaxValue(d.ToString("F0"));
Console.WriteLine($"{l2, -25}{dStr, -25}{l - l2, -10}{isHack}");
}
// .NETCoreApp,Version=v3.0
SRC STR DIFF HACK?
9223372036854775807 9223372036854775808 0 True
9223372036854775807 9223372036854775808 -1 True
9223372036854775807 9223372036854775808 -2 True
9223372036854775807 9223372036854775808 -100 True
9223372036854774784 9223372036854774784 23 False
-9223372036854775808 -9223372036854775808 0 False
-9223372036854775808 -9223372036854775808 1 False
-9223372036854775808 -9223372036854775808 2 False
1000 1000 0 False
-1000 -1000 0 False
0 0 0 False
Here are some examples for few ToString
formats.
var l1 = Int64.MaxValue;
Console.WriteLine($"Int64.MaxValue: {l1}");
double d = l1;
foreach(var x in new []{"C", "E", "F", "F0", "G", "G15", "G30", "N", "P", "R", "##########################"}) {
var dStr = d.ToString(x);
Console.WriteLine($"{x} {dStr}");
try { Console.WriteLine($"\t long diff: {long.Parse(dStr, NumberStyles.Any) - long.MaxValue}");}
catch (Exception ex) { Console.WriteLine($"\t long.Parse: {ex.Message}");};
try { Console.WriteLine($"\t ulong diff: {ulong.Parse(dStr, NumberStyles.Any) - long.MaxValue}");}
catch (Exception ex) { Console.WriteLine($"\t ulong.Parse: {ex.Message}");};
Console.WriteLine();
}
// .NETCoreApp,Version=v3.0
Int64.MaxValue: 9223372036854775807
C $9,223,372,036,854,775,808.00
long.Parse: Value was either too large or too small for an Int64.
ulong diff: 1
E 9.223372E+018
long diff: -36854775807
ulong diff: 18446744036854775809
F 9223372036854775808.00
long.Parse: Value was either too large or too small for an Int64.
ulong diff: 1
F0 9223372036854775808
long.Parse: Value was either too large or too small for an Int64.
ulong diff: 1
G 9.223372036854776E+18
long.Parse: Value was either too large or too small for an Int64.
ulong diff: 193
G15 9.22337203685478E+18
long.Parse: Value was either too large or too small for an Int64.
ulong diff: 4193
G30 9223372036854775808
long.Parse: Value was either too large or too small for an Int64.
ulong diff: 1
N 9,223,372,036,854,775,808.00
long.Parse: Value was either too large or too small for an Int64.
ulong diff: 1
P 922,337,203,685,477,580,800.00%
long.Parse: Input string was not in a correct format.
ulong.Parse: Input string was not in a correct format.
R 9.223372036854776E+18
long.Parse: Value was either too large or too small for an Int64.
ulong diff: 193
########################## 9223372036854780000
long.Parse: Value was either too large or too small for an Int64.
ulong diff: 4193
Upvotes: 1