[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Dotgnu-pnet-commits] CVS: pnetlib/runtime/System/Private NumberParser.
From: |
Jonathan Springer <address@hidden> |
Subject: |
[Dotgnu-pnet-commits] CVS: pnetlib/runtime/System/Private NumberParser.cs,1.9,1.10 |
Date: |
Mon, 17 Mar 2003 12:51:40 -0500 |
Update of /cvsroot/dotgnu-pnet/pnetlib/runtime/System/Private
In directory subversions:/tmp/cvs-serv26040/runtime/System/Private
Modified Files:
NumberParser.cs
Log Message:
Refinements/Fixes of FP Formatting/Parsing.
Index: NumberParser.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/runtime/System/Private/NumberParser.cs,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -r1.9 -r1.10
*** NumberParser.cs 2 Feb 2003 18:26:07 -0000 1.9
--- NumberParser.cs 17 Mar 2003 17:51:38 -0000 1.10
***************
*** 1111,1114 ****
--- 1111,1144 ----
}
+ // Array of powers of ten -- keeps precision within reason
+ private static double [] powten = {
+ 1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
+ 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
+ 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
+ 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20 };
+
+ // Build a number 10^exponent using the above array. This
+ // seems more precise than Math.Pow for two reasons:
+ // 1. The mantissa is a known constant.
+ // 2. The exponents are integral.
+ private static double Pow10(int exponent)
+ {
+ double ret = 1.0d;
+ int exp = exponent;
+
+ if (exp < 0)
+ {
+ for (; exp < -20; exp += 20) ret /= powten[20];
+ ret /= powten[exp*-1];
+ }
+ else
+ {
+ for (; exp > 20; exp -=20) ret *= powten[20];
+ ret *= powten[exp];
+ }
+
+ return ret;
+ }
+
public static double ParseDouble(String s, NumberStyles style,
NumberFormatInfo nfi)
***************
*** 1118,1185 ****
throw new FormatException(_("Format_HexNotSupported"));
StringBuilder sb = new StringBuilder(RawString(s, style, nfi));
-
bool negative = StripSign(sb, nfi);
! string str = sb.ToString();
! int stridx = 0;
!
! // Parse up to the decimal
! double work = 0.0d;
! while (stridx < str.Length
! && str[stridx] >= '0' && str[stridx] <= '9')
{
! work = work * 10.0d + (uint)(str[stridx++] - '0');
}
! // Parse after the decimal
! if (stridx < str.Length &&
!
str.Substring(stridx).StartsWith(nfi.NumberDecimalSeparator))
{
! stridx += nfi.NumberDecimalSeparator.Length;
! for (double mult = 0.1d;
! stridx < str.Length &&
! str[stridx] >= '0' && str[stridx] <=
'9';
! mult /= 10.0d)
! {
! work += (uint)(str[stridx++] - '0') * mult;
! }
}
// Parse after the exponent
! if (stridx < str.Length
! && (str[stridx] == 'e' || str[stridx] == 'E') )
{
! uint exponent = 0;
bool negExponent = false;
! stridx++;
! if (str.Substring(stridx).StartsWith(nfi.PositiveSign))
{
! stridx++;
}
! else if
(str.Substring(stridx).StartsWith(nfi.NegativeSign))
{
negExponent = true;
! stridx++;
}
- /* --- Removed in response to bug #2222
- else
- {
- // Darn it, we're supposed to have a sign.
- throw new
FormatException(_("Format_ExponentRequiresSign"));
- }
- */
! while (stridx < str.Length &&
! str[stridx] >= '0' && str[stridx] <=
'9')
! {
! exponent = 10 * exponent + (uint)(str[stridx++]
- '0');
! }
! work *= Math.Pow(10, exponent * (negExponent ? -1 : 1));
}
! if (stridx < str.Length)
{
// Oops. Throw a "junk found" exception.
--- 1148,1218 ----
throw new FormatException(_("Format_HexNotSupported"));
+ // Strip out the silliness
StringBuilder sb = new StringBuilder(RawString(s, style, nfi));
bool negative = StripSign(sb, nfi);
! // Figure out what our exponent was, then ditch the decimal
point
! int exponent = sb.ToString().IndexOf('.')-1;
! if (exponent == -2) // Not Found
{
! exponent = Math.Max(sb.ToString().IndexOf('e'),
!
sb.ToString().IndexOf('E')) - 1;
! if (exponent == -2) // Not Found
! exponent = sb.Length - 1;
}
+ else sb.Remove(exponent+1,1);
! // Remove leading zeroes that might gum up the works
! while (sb.Length > 0 && sb[0] == '0') {
! sb.Remove(0,1);
! exponent--;
! }
!
! // Guard case...
! if (sb.Length == 0) return 0.0;
! string str = sb.ToString();
!
! // Parse up to the exponent
! ulong ulwork = 0;
! int i;
!
! // This loop tops out at 18 -- the most digits in a ulong
! for (i = 0;
! i < str.Length && i < 18 && str[i] >= '0' &&
str[i] <= '9';
! i++)
{
! ulwork = (ulwork * 10) + unchecked((uint)(str[i]-'0'));
}
+ double work = (double)ulwork * Pow10(exponent - i + 1);
+
+ // Bleed off the over-precise numbers
+ while (i < str.Length && str[i] >= '0' && str[i] <= '9') i++;
// Parse after the exponent
! if (i < str.Length && (str[i] == 'e' || str[i] == 'E') )
{
! exponent = 0;
bool negExponent = false;
! i++;
!
! if (str.Substring(i).StartsWith(nfi.PositiveSign))
{
! i++;
}
! else if (str.Substring(i).StartsWith(nfi.NegativeSign))
{
negExponent = true;
! i++;
}
! while (i < str.Length && str[i] >= '0' && str[i] <= '9')
! exponent = (10*exponent) + (int)(str[i++] -
'0');
! if (negExponent) exponent *= -1;
! work *= Pow10(exponent);
}
! if (i < str.Length)
{
// Oops. Throw a "junk found" exception.
***************
*** 1191,1195 ****
return work;
}
-
}; // class NumberParser
--- 1224,1227 ----
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] CVS: pnetlib/runtime/System/Private NumberParser.cs,1.9,1.10,
Jonathan Springer <address@hidden> <=