Jump to page: 1 2
Thread overview
isNumeric.d - I'd like to contribute to Digital Mars D
Jun 02, 2005
David L. Davis
Jun 02, 2005
Andrew Fedoniouk
Jun 02, 2005
Derek Parnell
Jun 03, 2005
Derek Parnell
Jun 03, 2005
Kris
Jun 03, 2005
pragma
Jun 03, 2005
kris
Jun 03, 2005
Sean Kelly
Jun 03, 2005
Andrew Fedoniouk
Jun 03, 2005
Derek Parnell
Jun 03, 2005
David L. Davis
Re: toNumeric().d working version (uses isNumeric())
Jun 03, 2005
David L. Davis
June 02, 2005
I'd like to share what I've written which may help others in their own D code, and wish to contribute this code to Digital Mars D if Walter will accept it. I'm not sure exactly which module this code would best fit in if it's accepted, whether that would be in the std.string, std.math, or maybe in some a new std.misc module.

But anyway, I found that I needed a isNumeric() function for my variant (user-defined) datatype project, and already know I'll find it very useful in checking for numeric strings. After creating this code, I decided to scan the web for code others might have written for a isNumeric() function and to see if I might have missed anything important in my own function. But, to my surprise I found that most of them did something that was more of a isDigits() function than a isNumeric() function...which I thought was pretty darn odd. Well, I hope someone will find this code a tat-bit useful...enjoy! :)

# /+
#  ' Source        : isNumeric.d
#  ' Version       : v0.3
#  ' Author        : David L. 'SpottedTiger' Davis
#  ' Date Created  : 31.May.05 Compiled and Tested with dmd v0.125
#  ' Date Modified : 01.Jun.05 Modified the function to handle the
#  '               :           imaginary and complex float-point
#  '               :           datatypes.
#  '               :
#  ' Licence       : Public Domain / Contributed to Digital Mars
#  ' --------------------------------------------------------------
#  ' To Complie : C:\dmd>dmd mycode.d isnumeric.d
#  ' To Unittest: C:\dmd>dmd isnumeric.d -debug=isnumeric -unittest
#  +/
# module isnumeric;
#
# private import std.stdio;  // for writefln();
# private import std.string; // for tolower()
# private import std.stdarg; // for argument gathering
# private import std.utf;    // for toUTF8()
#
# /+
#  ' final bool isNumeric(in char[], in bool = false)
#  ' ---------------------------------------------------------------
#  ' [in] char[] s can be formatted in the following ways:
#  '
#  ' Integer Whole Number:
#  ' (for byte, ubyte, short, ushort, int, uint, long, and ulong)
#  ' ['+'|'-']digit(s)[U|L|UL]
#  '
#  ' examples: 123, 123UL, 123L, +123U, -123L
#  '
#  ' Floating-Point Number:
#  ' (for float, double, real, ifloat, idouble, and ireal)
#  ' ['+'|'-']digit(s)[.][digit(s)][[e-|e+]digit(s)][i|f|L|Li|fi]]
#  '      or [nan|nani|inf|-inf]
#  '
#  ' examples: +123., -123.01, 123.3e-10f, 123.3e-10fi, 123.3e-10L
#  '
#  ' (for cfloat, cdouble, and creal)
#  ' ['+'|'-']digit(s)[.][digit(s)][[e-|e+]digit(s)][+]
#  '         [digit(s)[.][digit(s)][[e-|e+]digit(s)][i|f|L|Li|fi]]
#  '      or [nan|nani|nan+nani|inf|-inf]
#  '
#  ' examples: nan, -123e-1+456.9e-10Li, +123e+10+456i, 123+456
#  '
#  ' [in] bool bAllowSep
#  ' False by default, but when set to true it will accept the
#  ' separator characters "," and "_" within the string, but these
#  ' characters should be stripped from the string before using any
#  ' of the conversion functions like toInt(), toFloat(), and etc
#  ' else an error will occur.
#  '
#  ' Also please note, that no spaces are allowed within the string
#  ' anywhere whether it's a leading, trailing, or embedded space(s),
#  ' thus they too must be stripped from the string before using this
#  ' function, or any of the conversion functions.
#  +/
# final bool isNumeric(in char[] s, in bool bAllowSep = false)
# {
#     int    iLen = s.length;
#     bool   bDecimalPoint = false;
#     bool   bExponent = false;
#     bool   bComplex = false;
#     char[] sx = std.string.tolower(s);
#     int    j  = 0;
#     char   c;
#
#     //writefln("isNumeric(char[], bool = false) called!");
#     // Empty string, return false
#     if (iLen == 0)
#         return false;
#
#     // Check for NaN (Not a Number)
#     if (sx == "nan" || sx == "nani" || sx == "nan+nani")
#         return true;
#
#     // Check for Infinity
#     if (sx == "inf" || sx == "-inf")
#         return true;
#
#     // A sign is allowed only in the 1st character
#     if (sx[0] == '-' || sx[0] == '+')
#         j++;
#
#     for (int i = j; i < iLen; i++)
#     {
#         c = sx[i];
#
#         // Digits are good, continue checking
#         // with the next character... ;)
#         if (c >= '0' && c <= '9')
#             continue;
#
#         // Check for the complex type, and if found
#         // reset the flags for checking the 2nd number.
#         else if (c == '+')
#             if (i > 0)
#             {
#                 bDecimalPoint = false;
#                 bExponent = false;
#                 bComplex = true;
#                 continue;
#             }
#             else
#                 return false;
#
#         // Allow only one exponent per number
#         else if (c == 'e')
#         {
#             // A 2nd exponent found, return not a number
#             if (bExponent)
#                 return false;
#
#             if (i + 1 < iLen)
#             {
#                 // Look forward for the sign, and if
#                 // missing then this is not a number.
#                 if (sx[i + 1] != '-' && sx[i + 1] != '+')
#                     return false;
#                 else
#                 {
#                     bExponent = true;
#                     i++;
#                 }
#             }
#             else
#                 // Ending in "E", return not a number
#                 return false;
#         }
#         // Allow only one decimal point per number to be used
#         else if (c == '.' )
#         {
#             // A 2nd decimal point found, return not a number
#             if (bDecimalPoint)
#                 return false;
#
#             bDecimalPoint = true;
#             continue;
#         }
#         // Check for ending literal characters: "f,u,l,i,ul,fi,li",
#         // and wheater they're being used with the correct datatype.
#         else if (i == iLen - 2)
#         {
#             // Integer Whole Number
#             if (sx[i..iLen] == "ul" &&
#                (!bDecimalPoint && !bExponent && !bComplex))
#                 return true;
#             // Floating-Point Number
#             else if ((sx[i..iLen] == "fi" || sx[i..iLen] == "li") &&
#                      (bDecimalPoint || bExponent || bComplex))
#                 return true;
#             else if (sx[i..iLen] == "ul" &&
#                     (bDecimalPoint || bExponent || bComplex))
#                 return false;
#             // Could be a Integer or a Float, thus
#             // all these suffixes are valid for both
#             else if (sx[i..iLen] == "ul" ||
#                      sx[i..iLen] == "fi" ||
#                      sx[i..iLen] == "li")
#                 return true;
#             else
#                 return false;
#         }
#         else if (i == iLen - 1)
#         {
#             // Integer Whole Number
#             if ((c == 'u' || c == 'l') &&
#                 (!bDecimalPoint && !bExponent && !bComplex))
#                 return true;
#             // Check to see if the last character in the string
#             // is the required 'i' character
#             else if (bComplex)
#                 if (c == 'i')
#                     return true;
#                 else
#                     return false;
#             // Floating-Point Number
#             else if ((c == 'l' || c == 'f' || c == 'i') &&
#                      (bDecimalPoint || bExponent))
#                 return true;
#             // Could be a Integer or a Float, thus
#             // all these suffixes are valid for both
#             else if (c == 'l' || c == 'f' || c == 'i')
#                 return true;
#             else
#                 return false;
#         }
#         else
#             // Check if separators are allow
#             // to be in the numeric string
#             if (bAllowSep == true && (c == '_' || c == ','))
#                 continue;
#             else
#                 return false;
#     }
#
#     return true;
# }
#
# // Allow any object as a parameter
# bool isNumeric(...)
# {
#     return isNumeric(_arguments, _argptr);
# }
#
# // Check only the first parameter, all others will be ignored.
# bool isNumeric(TypeInfo[] _arguments, va_list _argptr)
# {
#     char[]  s  = "";
#     wchar[] ws = "";
#     dchar[] ds = "";
#
#     //writefln("isNumeric(...) called!");
#     if (_arguments.length == 0)
#         return false;
#
#     if (_arguments[0] == typeid(char[]))
#         return isNumeric(va_arg!(char[])(_argptr));
#     else if (_arguments[0] == typeid(wchar[]))
#         return isNumeric(std.utf.toUTF8(va_arg!(wchar[])(_argptr)));
#     else if (_arguments[0] == typeid(dchar[]))
#         return isNumeric(std.utf.toUTF8(va_arg!(dchar[])(_argptr)));
#     else if (_arguments[0] == typeid(real))
#         return true;
#     else if (_arguments[0] == typeid(double))
#         return true;
#     else if (_arguments[0] == typeid(float))
#         return true;
#     else if (_arguments[0] == typeid(ulong))
#         return true;
#     else if (_arguments[0] == typeid(long))
#         return true;
#     else if (_arguments[0] == typeid(uint))
#         return true;
#     else if (_arguments[0] == typeid(int))
#         return true;
#     else if (_arguments[0] == typeid(ushort))
#         return true;
#     else if (_arguments[0] == typeid(short))
#         return true;
#     else if (_arguments[0] == typeid(ubyte))
#     {
#        s.length = 1;
#        s[0]= va_arg!(ubyte)(_argptr);
#        return isNumeric(cast(char[])s);
#     }
#     else if (_arguments[0] == typeid(byte))
#     {
#        s.length = 1;
#        s[0] = va_arg!(byte)(_argptr);
#        return isNumeric(cast(char[])s);
#     }
#     else if (_arguments[0] == typeid(ireal))
#         return true;
#     else if (_arguments[0] == typeid(idouble))
#         return true;
#     else if (_arguments[0] == typeid(ifloat))
#         return true;
#     else if (_arguments[0] == typeid(creal))
#         return true;
#     else if (_arguments[0] == typeid(cdouble))
#         return true;
#     else if (_arguments[0] == typeid(cfloat))
#         return true;
#     else if (_arguments[0] == typeid(char))
#     {
#         s.length = 1;
#         s[0] = va_arg!(char)(_argptr);
#         return isNumeric(s);
#     }
#     else if (_arguments[0] == typeid(wchar))
#     {
#         ws.length = 1;
#         ws[0] = va_arg!(wchar)(_argptr);
#         return isNumeric(std.utf.toUTF8(ws));
#     }
#     else if (_arguments[0] == typeid(dchar))
#     {
#         ds.length =  1;
#         ds[0] = va_arg!(dchar)(_argptr);
#         return isNumeric(std.utf.toUTF8(ds));
#     }
#     //else if (_arguments[0] == typeid(cent))
#     //    return true;
#     //else if (_arguments[0] == typeid(ucent))
#     //    return true;
#     else
#        return false;
# }
#
# unittest
# {
#     writefln( "isNumeric(in char[], bool = false).unittest" );
#     char[] s;
#
#     // Test the isNumeric(in char[]) function
#     assert(isNumeric("1") == true );
#     assert(isNumeric("1.0") == true );
#     assert(isNumeric("1e-1") == true );
#     assert(isNumeric("12345xxxx890") == false );
#     assert(isNumeric("567L") == true );
#     assert(isNumeric("23UL") == true );
#     assert(isNumeric("-123..56f") == false );
#     assert(isNumeric("12.3.5.6") == false );
#     assert(isNumeric(" 12.356") == false );
#     assert(isNumeric("123 5.6") == false );
#     assert(isNumeric("1233E-1+1.0e-1i") == true );
#
#     assert(isNumeric("123.00E-5+1234.45E-12Li") == true);
#     assert(isNumeric("123.00e-5+1234.45E-12iL") == false);
#     assert(isNumeric("123.00e-5+1234.45e-12uL") == false);
#     assert(isNumeric("123.00E-5+1234.45e-12lu") == false);
#
#     assert(isNumeric("123fi") == true);
#     assert(isNumeric("123li") == true);
#     assert(isNumeric("--123L") == false);
#     assert(isNumeric("+123.5UL") == false);
#     assert(isNumeric("123f") == true);
#     assert(isNumeric("123.u") == false);
#
#     assert(isNumeric(std.string.toString(real.nan)) == true);
#     assert(isNumeric(std.string.toString(-real.infinity)) == true);
#     assert(isNumeric(std.string.toString(123e+2+1234.78Li)) == true);
#
#     s = "$250.99-";
#     assert(isNumeric(s[1..s.length - 2]) == true);
#     assert(isNumeric(s) == false);
#     assert(isNumeric(s[0..s.length - 1]) == false);
#
#     // These test calling the isNumeric(...) function
#     assert(isNumeric(1,123UL) == true);
#     assert(isNumeric('2') == true);
#     assert(isNumeric('x') == false);
#     assert(isNumeric(cast(byte)0x57) == false); // 'W'
#     assert(isNumeric(cast(byte)0x37) == true);  // '7'
#     assert(isNumeric(cast(wchar[])"145.67") == true);
#     assert(isNumeric(cast(dchar[])"145.67U") == false);
#     assert(isNumeric(123_000.23fi) == true);
#     assert(isNumeric(123.00E-5+1234.45E-12Li) == true);
#     assert(isNumeric(real.nan) == true);
#     assert(isNumeric(-real.infinity) == true);
# }
#
# debug( isnumeric )
# {
# int main()
# {
#     writefln("unittest done!");
#     return 0;
# }
# }

David L.

-------------------------------------------------------------------
"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
-------------------------------------------------------------------

MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html
June 02, 2005
Cool!

David, would it be possible to write also toNumeric ?

Like this:

std.boxer.Box  toNumeric(const char[] s, bool bAllowSep = false)

?

Andrew.






"David L. Davis" <SpottedTiger@yahoo.com> wrote in message news:d7m0nf$3s0$1@digitaldaemon.com...
> I'd like to share what I've written which may help others in their own D
> code,
> and wish to contribute this code to Digital Mars D if Walter will accept
> it. I'm
> not sure exactly which module this code would best fit in if it's
> accepted,
> whether that would be in the std.string, std.math, or maybe in some a new
> std.misc module.
>
> But anyway, I found that I needed a isNumeric() function for my variant
> (user-defined) datatype project, and already know I'll find it very useful
> in
> checking for numeric strings. After creating this code, I decided to scan
> the
> web for code others might have written for a isNumeric() function and to
> see if
> I might have missed anything important in my own function. But, to my
> surprise I
> found that most of them did something that was more of a isDigits()
> function
> than a isNumeric() function...which I thought was pretty darn odd. Well, I
> hope
> someone will find this code a tat-bit useful...enjoy! :)
>
> # /+
> #  ' Source        : isNumeric.d
> #  ' Version       : v0.3
> #  ' Author        : David L. 'SpottedTiger' Davis
> #  ' Date Created  : 31.May.05 Compiled and Tested with dmd v0.125
> #  ' Date Modified : 01.Jun.05 Modified the function to handle the
> #  '               :           imaginary and complex float-point
> #  '               :           datatypes.
> #  '               :
> #  ' Licence       : Public Domain / Contributed to Digital Mars
> #  ' --------------------------------------------------------------
> #  ' To Complie : C:\dmd>dmd mycode.d isnumeric.d
> #  ' To Unittest: C:\dmd>dmd isnumeric.d -debug=isnumeric -unittest
> #  +/
> # module isnumeric;
> #
> # private import std.stdio;  // for writefln();
> # private import std.string; // for tolower()
> # private import std.stdarg; // for argument gathering
> # private import std.utf;    // for toUTF8()
> #
> # /+
> #  ' final bool isNumeric(in char[], in bool = false)
> #  ' ---------------------------------------------------------------
> #  ' [in] char[] s can be formatted in the following ways:
> #  '
> #  ' Integer Whole Number:
> #  ' (for byte, ubyte, short, ushort, int, uint, long, and ulong)
> #  ' ['+'|'-']digit(s)[U|L|UL]
> #  '
> #  ' examples: 123, 123UL, 123L, +123U, -123L
> #  '
> #  ' Floating-Point Number:
> #  ' (for float, double, real, ifloat, idouble, and ireal)
> #  ' ['+'|'-']digit(s)[.][digit(s)][[e-|e+]digit(s)][i|f|L|Li|fi]]
> #  '      or [nan|nani|inf|-inf]
> #  '
> #  ' examples: +123., -123.01, 123.3e-10f, 123.3e-10fi, 123.3e-10L
> #  '
> #  ' (for cfloat, cdouble, and creal)
> #  ' ['+'|'-']digit(s)[.][digit(s)][[e-|e+]digit(s)][+]
> #  '         [digit(s)[.][digit(s)][[e-|e+]digit(s)][i|f|L|Li|fi]]
> #  '      or [nan|nani|nan+nani|inf|-inf]
> #  '
> #  ' examples: nan, -123e-1+456.9e-10Li, +123e+10+456i, 123+456
> #  '
> #  ' [in] bool bAllowSep
> #  ' False by default, but when set to true it will accept the
> #  ' separator characters "," and "_" within the string, but these
> #  ' characters should be stripped from the string before using any
> #  ' of the conversion functions like toInt(), toFloat(), and etc
> #  ' else an error will occur.
> #  '
> #  ' Also please note, that no spaces are allowed within the string
> #  ' anywhere whether it's a leading, trailing, or embedded space(s),
> #  ' thus they too must be stripped from the string before using this
> #  ' function, or any of the conversion functions.
> #  +/
> # final bool isNumeric(in char[] s, in bool bAllowSep = false)
> # {
> #     int    iLen = s.length;
> #     bool   bDecimalPoint = false;
> #     bool   bExponent = false;
> #     bool   bComplex = false;
> #     char[] sx = std.string.tolower(s);
> #     int    j  = 0;
> #     char   c;
> #
> #     //writefln("isNumeric(char[], bool = false) called!");
> #     // Empty string, return false
> #     if (iLen == 0)
> #         return false;
> #
> #     // Check for NaN (Not a Number)
> #     if (sx == "nan" || sx == "nani" || sx == "nan+nani")
> #         return true;
> #
> #     // Check for Infinity
> #     if (sx == "inf" || sx == "-inf")
> #         return true;
> #
> #     // A sign is allowed only in the 1st character
> #     if (sx[0] == '-' || sx[0] == '+')
> #         j++;
> #
> #     for (int i = j; i < iLen; i++)
> #     {
> #         c = sx[i];
> #
> #         // Digits are good, continue checking
> #         // with the next character... ;)
> #         if (c >= '0' && c <= '9')
> #             continue;
> #
> #         // Check for the complex type, and if found
> #         // reset the flags for checking the 2nd number.
> #         else if (c == '+')
> #             if (i > 0)
> #             {
> #                 bDecimalPoint = false;
> #                 bExponent = false;
> #                 bComplex = true;
> #                 continue;
> #             }
> #             else
> #                 return false;
> #
> #         // Allow only one exponent per number
> #         else if (c == 'e')
> #         {
> #             // A 2nd exponent found, return not a number
> #             if (bExponent)
> #                 return false;
> #
> #             if (i + 1 < iLen)
> #             {
> #                 // Look forward for the sign, and if
> #                 // missing then this is not a number.
> #                 if (sx[i + 1] != '-' && sx[i + 1] != '+')
> #                     return false;
> #                 else
> #                 {
> #                     bExponent = true;
> #                     i++;
> #                 }
> #             }
> #             else
> #                 // Ending in "E", return not a number
> #                 return false;
> #         }
> #         // Allow only one decimal point per number to be used
> #         else if (c == '.' )
> #         {
> #             // A 2nd decimal point found, return not a number
> #             if (bDecimalPoint)
> #                 return false;
> #
> #             bDecimalPoint = true;
> #             continue;
> #         }
> #         // Check for ending literal characters: "f,u,l,i,ul,fi,li",
> #         // and wheater they're being used with the correct datatype.
> #         else if (i == iLen - 2)
> #         {
> #             // Integer Whole Number
> #             if (sx[i..iLen] == "ul" &&
> #                (!bDecimalPoint && !bExponent && !bComplex))
> #                 return true;
> #             // Floating-Point Number
> #             else if ((sx[i..iLen] == "fi" || sx[i..iLen] == "li") &&
> #                      (bDecimalPoint || bExponent || bComplex))
> #                 return true;
> #             else if (sx[i..iLen] == "ul" &&
> #                     (bDecimalPoint || bExponent || bComplex))
> #                 return false;
> #             // Could be a Integer or a Float, thus
> #             // all these suffixes are valid for both
> #             else if (sx[i..iLen] == "ul" ||
> #                      sx[i..iLen] == "fi" ||
> #                      sx[i..iLen] == "li")
> #                 return true;
> #             else
> #                 return false;
> #         }
> #         else if (i == iLen - 1)
> #         {
> #             // Integer Whole Number
> #             if ((c == 'u' || c == 'l') &&
> #                 (!bDecimalPoint && !bExponent && !bComplex))
> #                 return true;
> #             // Check to see if the last character in the string
> #             // is the required 'i' character
> #             else if (bComplex)
> #                 if (c == 'i')
> #                     return true;
> #                 else
> #                     return false;
> #             // Floating-Point Number
> #             else if ((c == 'l' || c == 'f' || c == 'i') &&
> #                      (bDecimalPoint || bExponent))
> #                 return true;
> #             // Could be a Integer or a Float, thus
> #             // all these suffixes are valid for both
> #             else if (c == 'l' || c == 'f' || c == 'i')
> #                 return true;
> #             else
> #                 return false;
> #         }
> #         else
> #             // Check if separators are allow
> #             // to be in the numeric string
> #             if (bAllowSep == true && (c == '_' || c == ','))
> #                 continue;
> #             else
> #                 return false;
> #     }
> #
> #     return true;
> # }
> #
> # // Allow any object as a parameter
> # bool isNumeric(...)
> # {
> #     return isNumeric(_arguments, _argptr);
> # }
> #
> # // Check only the first parameter, all others will be ignored.
> # bool isNumeric(TypeInfo[] _arguments, va_list _argptr)
> # {
> #     char[]  s  = "";
> #     wchar[] ws = "";
> #     dchar[] ds = "";
> #
> #     //writefln("isNumeric(...) called!");
> #     if (_arguments.length == 0)
> #         return false;
> #
> #     if (_arguments[0] == typeid(char[]))
> #         return isNumeric(va_arg!(char[])(_argptr));
> #     else if (_arguments[0] == typeid(wchar[]))
> #         return isNumeric(std.utf.toUTF8(va_arg!(wchar[])(_argptr)));
> #     else if (_arguments[0] == typeid(dchar[]))
> #         return isNumeric(std.utf.toUTF8(va_arg!(dchar[])(_argptr)));
> #     else if (_arguments[0] == typeid(real))
> #         return true;
> #     else if (_arguments[0] == typeid(double))
> #         return true;
> #     else if (_arguments[0] == typeid(float))
> #         return true;
> #     else if (_arguments[0] == typeid(ulong))
> #         return true;
> #     else if (_arguments[0] == typeid(long))
> #         return true;
> #     else if (_arguments[0] == typeid(uint))
> #         return true;
> #     else if (_arguments[0] == typeid(int))
> #         return true;
> #     else if (_arguments[0] == typeid(ushort))
> #         return true;
> #     else if (_arguments[0] == typeid(short))
> #         return true;
> #     else if (_arguments[0] == typeid(ubyte))
> #     {
> #        s.length = 1;
> #        s[0]= va_arg!(ubyte)(_argptr);
> #        return isNumeric(cast(char[])s);
> #     }
> #     else if (_arguments[0] == typeid(byte))
> #     {
> #        s.length = 1;
> #        s[0] = va_arg!(byte)(_argptr);
> #        return isNumeric(cast(char[])s);
> #     }
> #     else if (_arguments[0] == typeid(ireal))
> #         return true;
> #     else if (_arguments[0] == typeid(idouble))
> #         return true;
> #     else if (_arguments[0] == typeid(ifloat))
> #         return true;
> #     else if (_arguments[0] == typeid(creal))
> #         return true;
> #     else if (_arguments[0] == typeid(cdouble))
> #         return true;
> #     else if (_arguments[0] == typeid(cfloat))
> #         return true;
> #     else if (_arguments[0] == typeid(char))
> #     {
> #         s.length = 1;
> #         s[0] = va_arg!(char)(_argptr);
> #         return isNumeric(s);
> #     }
> #     else if (_arguments[0] == typeid(wchar))
> #     {
> #         ws.length = 1;
> #         ws[0] = va_arg!(wchar)(_argptr);
> #         return isNumeric(std.utf.toUTF8(ws));
> #     }
> #     else if (_arguments[0] == typeid(dchar))
> #     {
> #         ds.length =  1;
> #         ds[0] = va_arg!(dchar)(_argptr);
> #         return isNumeric(std.utf.toUTF8(ds));
> #     }
> #     //else if (_arguments[0] == typeid(cent))
> #     //    return true;
> #     //else if (_arguments[0] == typeid(ucent))
> #     //    return true;
> #     else
> #        return false;
> # }
> #
> # unittest
> # {
> #     writefln( "isNumeric(in char[], bool = false).unittest" );
> #     char[] s;
> #
> #     // Test the isNumeric(in char[]) function
> #     assert(isNumeric("1") == true );
> #     assert(isNumeric("1.0") == true );
> #     assert(isNumeric("1e-1") == true );
> #     assert(isNumeric("12345xxxx890") == false );
> #     assert(isNumeric("567L") == true );
> #     assert(isNumeric("23UL") == true );
> #     assert(isNumeric("-123..56f") == false );
> #     assert(isNumeric("12.3.5.6") == false );
> #     assert(isNumeric(" 12.356") == false );
> #     assert(isNumeric("123 5.6") == false );
> #     assert(isNumeric("1233E-1+1.0e-1i") == true );
> #
> #     assert(isNumeric("123.00E-5+1234.45E-12Li") == true);
> #     assert(isNumeric("123.00e-5+1234.45E-12iL") == false);
> #     assert(isNumeric("123.00e-5+1234.45e-12uL") == false);
> #     assert(isNumeric("123.00E-5+1234.45e-12lu") == false);
> #
> #     assert(isNumeric("123fi") == true);
> #     assert(isNumeric("123li") == true);
> #     assert(isNumeric("--123L") == false);
> #     assert(isNumeric("+123.5UL") == false);
> #     assert(isNumeric("123f") == true);
> #     assert(isNumeric("123.u") == false);
> #
> #     assert(isNumeric(std.string.toString(real.nan)) == true);
> #     assert(isNumeric(std.string.toString(-real.infinity)) == true);
> #     assert(isNumeric(std.string.toString(123e+2+1234.78Li)) == true);
> #
> #     s = "$250.99-";
> #     assert(isNumeric(s[1..s.length - 2]) == true);
> #     assert(isNumeric(s) == false);
> #     assert(isNumeric(s[0..s.length - 1]) == false);
> #
> #     // These test calling the isNumeric(...) function
> #     assert(isNumeric(1,123UL) == true);
> #     assert(isNumeric('2') == true);
> #     assert(isNumeric('x') == false);
> #     assert(isNumeric(cast(byte)0x57) == false); // 'W'
> #     assert(isNumeric(cast(byte)0x37) == true);  // '7'
> #     assert(isNumeric(cast(wchar[])"145.67") == true);
> #     assert(isNumeric(cast(dchar[])"145.67U") == false);
> #     assert(isNumeric(123_000.23fi) == true);
> #     assert(isNumeric(123.00E-5+1234.45E-12Li) == true);
> #     assert(isNumeric(real.nan) == true);
> #     assert(isNumeric(-real.infinity) == true);
> # }
> #
> # debug( isnumeric )
> # {
> # int main()
> # {
> #     writefln("unittest done!");
> #     return 0;
> # }
> # }
>
> David L.
>
> -------------------------------------------------------------------
> "Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
> -------------------------------------------------------------------
>
> MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html


June 02, 2005
On Thu, 2 Jun 2005 15:26:27 -0700, Andrew Fedoniouk wrote:

> Cool!
> 
> David, would it be possible to write also toNumeric ?
> 
> Like this:
> 
> std.boxer.Box  toNumeric(const char[] s, bool bAllowSep = false)

I just wrote one of those a couple of days ago. Its a part of a new application I'm writing but I guess I can split it out ... give me a few moments ...

-- 
Derek
Melbourne, Australia
3/06/2005 8:57:45 AM
June 03, 2005
On Fri, 3 Jun 2005 08:59:41 +1000, Derek Parnell wrote:

> On Thu, 2 Jun 2005 15:26:27 -0700, Andrew Fedoniouk wrote:
> 
>> Cool!
>> 
>> David, would it be possible to write also toNumeric ?
>> 
>> Like this:
>> 
>> std.boxer.Box  toNumeric(const char[] s, bool bAllowSep = false)
> 
> I just wrote one of those a couple of days ago. Its a part of a new application I'm writing but I guess I can split it out ... give me a few moments ...

Here is my version attached ;-)

 real TextToNumber( dchar[] pText, out int pStopPosn, bool pNotify = true);

Hope somebody finds it useful.

-- 
Derek
Melbourne, Australia
3/06/2005 10:32:49 AM

June 03, 2005
Cool!

Mango.format has similar stuff for formatting and parsing numbers: e.g. http://svn.dsource.org/projects/mango/trunk/mango/format/Double.d

There's also a more powerful version using David Gay's dtoa.c code. You really should take a look at what that C file does ~ it's kinda' frightening!

http://svn.dsource.org/projects/mango/trunk/mango/format/dtoa.c http://svn.dsource.org/projects/mango/trunk/mango/format/DGDouble.d

- Kris


"Derek Parnell" <derek@psych.ward> wrote in message news:bo1091wvq352$.1noqjnreoaasw$.dlg@40tude.net...
> On Fri, 3 Jun 2005 08:59:41 +1000, Derek Parnell wrote:
>
> > On Thu, 2 Jun 2005 15:26:27 -0700, Andrew Fedoniouk wrote:
> >
> >> Cool!
> >>
> >> David, would it be possible to write also toNumeric ?
> >>
> >> Like this:
> >>
> >> std.boxer.Box  toNumeric(const char[] s, bool bAllowSep = false)
> >
> > I just wrote one of those a couple of days ago. Its a part of a new application I'm writing but I guess I can split it out ... give me a few moments ...
>
> Here is my version attached ;-)
>
>  real TextToNumber( dchar[] pText, out int pStopPosn, bool pNotify =
true);
>
> Hope somebody finds it useful.
>
> -- 
> Derek
> Melbourne, Australia
> 3/06/2005 10:32:49 AM


June 03, 2005


"Derek Parnell" <derek@psych.ward> wrote in message news:bo1091wvq352$.1noqjnreoaasw$.dlg@40tude.net...
> On Fri, 3 Jun 2005 08:59:41 +1000, Derek Parnell wrote:
>
>> On Thu, 2 Jun 2005 15:26:27 -0700, Andrew Fedoniouk wrote:
>>
>>> Cool!
>>>
>>> David, would it be possible to write also toNumeric ?
>>>
>>> Like this:
>>>
>>> std.boxer.Box  toNumeric(const char[] s, bool bAllowSep = false)
>>
>> I just wrote one of those a couple of days ago. Its a part of a new application I'm writing but I guess I can split it out ... give me a few moments ...
>
> Here is my version attached ;-)
>
> real TextToNumber( dchar[] pText, out int pStopPosn, bool pNotify = true);
>
> Hope somebody finds it useful.

Nice, Derek,

One thought:

to have returning value as box allows:

1) to detect was it value at all;
2) to select the most compact storage form.
3) to be more precise - casting real to int is always something from
    fuzzy logic field.

Just my guess.

Andrew.



>
> -- 
> Derek
> Melbourne, Australia
> 3/06/2005 10:32:49 AM


June 03, 2005
In article <d7o12k$2dv4$1@digitaldaemon.com>, Andrew Fedoniouk says...
>
>Cool!
>
>David, would it be possible to write also toNumeric ?
>
>Like this:
>
>std.boxer.Box  toNumeric(const char[] s, bool bAllowSep = false)
>
>?
>
>Andrew.

Andrew, here's what I came up with so far...what do you think? (Note: that this uses the isNumeric.d code as an import)

# /+
#  ' Source : toNumeric.d - Convert a numeric string into a boxed numeric
#  ' Author : David L. 'SpottedTiger' Davis
#  ' Created: 02.Jun.05
#  ' License: Public Domain
#  ' -----------------------------------------------------------
#  ' Note   : When using the std.boxer module, always compile
#  '          with the "-release" dmd commandline switch,
#  '          otherwise you'll get a linker error.
#  ' -----------------------------------------------------------
#  ' To Compile: dmd mycode.d tonumeric.d isnumeric.d -release
#  +/
# private import std.stdio;
# private import std.boxer; // now in D v0.124
# private import std.conv;
# private import isnumeric;
#
# Box toNumeric( in char[] s, in bool bAllowSep = false)
# {
#     Box    boxx;
#     char[] sx        = std.string.strip(s);
#     int    iLen      = s.length;
#     bool   bComplex  = false;
#     bool   bNeg      = false;
#     bool   bExponent = false;
#     bool   bISuffix  = false;
#     bool   bInt      = true;
#     int    j         = 0;
#     char   c;
#     long   l         = 0L;
#     ulong  ul        = 0UL;
#     real   r         = real.nan;
#     //ireal  ir        = ireal.nan;
#     //creal  cr        = creal.nan;
#
#     // Check first for NaN and Infinity
#     if (sx == "nan")
#     { boxx = box(real.nan); return boxx; }
#     else if (sx == "inf")
#     { boxx = box(real.infinity); return boxx; }
#     else if (sx == "-inf")
#     { boxx = box(-real.infinity); return boxx; }
#     else if (sx == "nani")
#     { boxx = box(ireal.nan); return boxx; }
#     else if (sx == "nan+nani")
#     { boxx = box(creal.re.nan+creal.im.nan); return boxx; }
#
#     // If valid numeric string, set flags before boxing,
#     // else throw an Exception that its not a numeric string.
#     if (isNumeric(sx, bAllowSep))
#     {
#         if (sx[0] == '+')
#             j++;
#
#         // Is a negative number
#         else if (sx[0] == '-')
#         {
#             j++;
#             bNeg = true;
#         }
#
#         for (int i = j; i < s.length; i++)
#         {
#             c = s[i];
#
#             // Decimal found, number is a floating-point
#             if (c == '.')
#                 bInt = false;
#             else if (c == 'e' || c == 'E')
#             {
#                 i++;
#                 // if two exponents found, then
#                 // this is a complex float
#                 if (bExponent)
#                     bComplex = true;
#
#                 bExponent = true;
#                 bInt = false;
#                 continue;
#             }
#             // A single plus-sign found after
#             // the first position, makes this a
#             // complex float.
#             else if (c == '+')
#                 bComplex = true;
#             else if (c == 'i' || c == 'I')
#                 bISuffix = true;
#             else {}
#         }
#     }
#     else
#     {
#         throw new Exception("Error in toNumeric(in char[], " ~
#                             "in bool = false), the first parameter " ~
#                             s ~ " is not a numeric string!");
#     }
#
#     // Remove Separators
#     if (bAllowSep)
#     {
#         sx = std.string.replace(sx, "_", "");
#         sx = std.string.replace(sx, ",", "");
#     }
#
#     // Remove suffixes other than 'i' before
#     // calling the conversion functions
#     c = sx[sx.length - 1];
#     if (c == 'f' || c == 'F' || c == 'l' ||
#         c == 'L' || c == 'u' || c == 'U')
#         sx.length = s.length - 1;
#
#     c = sx[sx.length - 1];
#     if (c == 'f' || c == 'F' || c == 'l' ||
#         c == 'L' || c == 'u' || c == 'U')
#         sx.length = s.length - 1;
#
#     // Positive Whole Number
#     if (bInt && !bNeg)
#     {
#         //writefln("Unsigned Int");
#         ul = std.conv.toUlong(sx);
#         if (ul <= ubyte.max)
#             boxx = box(cast(ubyte)ul);
#         else if (ul <= ushort.max)
#             boxx = box(cast(ushort)ul);
#         else if (ul <= uint.max)
#             boxx = box(cast(uint)ul);
#         else
#             boxx = box(ul);
#     }
#     // Negative Whole Numer
#     else if (bInt && bNeg)
#     {
#         //writefln("Signed Int");
#         l = std.conv.toLong(sx);
#         if (l <= byte.max)
#             boxx = box(cast(byte)l);
#         else if (l <= short.max)
#             boxx = box(cast(short)l);
#         else if (l <= int.max)
#             boxx = box(cast(int)l);
#         else
#             boxx = box(cast(long)l);
#     }
#     // Regular Floating-Point Number
#     else if (!bISuffix && !bComplex)
#     {
#         //writefln("Regular Float");
#         r = std.conv.toReal(sx);
#         if (r <= float.max)
#             boxx = box(cast(float)r);
#         else if (r <= double.max)
#             boxx = box(cast(double)r);
#         else
#             boxx = box(r);
#     }
# /******************************************************/
# /*  ** Walter is still working on putting these in ** */
# /******************************************************/
#     // Imaginary Floating-Point Number
#     else if (bISuffix && !bComplex)
#     {
#         //writefln("Imaginary Float");
#
#         //ir = std.conv.toIreal(sx);
#         //if (ir <= ifloat.max)
#         //    boxx = box(cast(ifloat)ir);
#         //else if (ir <= idouble.max)
#         //    boxx = box(cast(idouble)ir);
#         //else
#         //    boxx = box(ir);
#
#         //** Temp fix until the toIreal() is ready in std.conv **
#         sx = sx[0..sx.length - 2];
#         r = std.conv.toReal(sx);
#         if (r <= float.max)
#             boxx = box(cast(ifloat)(r * 1.0i));
#         else if (r <= double.max)
#             boxx = box(cast(idouble)(r * 1.0i));
#         else
#             boxx = box(cast(ireal)(r * 1.0i));
#     }
#     // Complex Floating-Point Number
#     /+
#     else if (bComplex)
#     {
#         //writefln("Complex Float");
#         //cr = std.conv.toCreal(sx);
#         //boxx = box(cr);
#     }
#     +/
#     else
#     {
#         //writefln("Unknown");
#         throw new Exception("Error in toNumeric(in char[], " ~
#                             "in bool = false), the first parameter " ~
#                             s ~ " is not a numeric string!");
#     }
#
#     return boxx;
# }
#
# void main()
# {
#     Box wx;
#
#     wx = toNumeric("123");
#     writefln("unbox!(uint)(wx)=%d", unbox!(uint)(wx));
#
#     wx = toNumeric("-12L");
#     writefln("unbox!(long)(wx)=%8d", unbox!(long)(wx));
#
#     wx = toNumeric("1.234");
#     writefln("unbox!(double)(wx)=%8.3f", unbox!(double)(wx));
#
#     wx = toNumeric("1.234fi");
#     writefln("unbox!(ifloat)(wx=%8.3f", unbox!(ifloat)(wx));
#
#     wx = toNumeric("1.234e+12");
#     writefln("unbox!(float)(wx)=%8.4g", unbox!(float)(wx));
#
#
#     //Can't do until toCreal() is ready in std.conv
#     //wx = toNumeric("1.234e+12+345.4e+34i");
#     //writefln("cr=%g", creal.re.nan+creal.im.nan);
# }

Output:
-----------------
C:\dmd>dmd tonumeric.d isNumeric.d -release C:\dmd\bin\..\..\dm\bin\link.exe tonumeric+isNumeric,,,user32+kernel32/noi;

C:\dmd>tonumeric
unbox!(uint)(wx)=123
unbox!(long)(wx)=-12
unbox!(double)(wx)=    1.234
unbox!(ifloat)(wx=    1.234
unbox!(float)(wx)=1.234e+12

C:\dmd>

David L.

-------------------------------------------------------------------
"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
-------------------------------------------------------------------

MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html
June 03, 2005
On Thu, 2 Jun 2005 21:33:45 -0700, Andrew Fedoniouk wrote:


[snip]
> One thought:
> 
> to have returning value as box allows:
> 
> 1) to detect was it value at all;
> 2) to select the most compact storage form.
> 3) to be more precise - casting real to int is always something from
>     fuzzy logic field.

This was ported from another language and before the boxer module was available.

I'll have go at implementing your suggestion though ... wish me luck ;-)

-- 
Derek
Melbourne, Australia
3/06/2005 3:01:16 PM
June 03, 2005
In article <d7odh0$2mv2$1@digitaldaemon.com>, Kris says...
>
>Cool!
>
>Mango.format has similar stuff for formatting and parsing numbers: e.g. http://svn.dsource.org/projects/mango/trunk/mango/format/Double.d
>
>There's also a more powerful version using David Gay's dtoa.c code. You really should take a look at what that C file does ~ it's kinda' frightening!
>
>http://svn.dsource.org/projects/mango/trunk/mango/format/dtoa.c http://svn.dsource.org/projects/mango/trunk/mango/format/DGDouble.d
>
>- Kris

[reading dtoa.c]

"kinda' frigtening" doesn't even begin to describe it.  Not only am I reminded of why I switched to D, but I actually feel a touch queasy now.

Here's to cleaner solutions and better looking code.

- EricAnderton at yahoo
June 03, 2005
pragma wrote:
> In article <d7odh0$2mv2$1@digitaldaemon.com>, Kris says...
> 
>>Cool!
>>
>>Mango.format has similar stuff for formatting and parsing numbers: e.g.
>>http://svn.dsource.org/projects/mango/trunk/mango/format/Double.d
>>
>>There's also a more powerful version using David Gay's dtoa.c code. You
>>really should take a look at what that C file does ~ it's kinda'
>>frightening!
>>
>>http://svn.dsource.org/projects/mango/trunk/mango/format/dtoa.c
>>http://svn.dsource.org/projects/mango/trunk/mango/format/DGDouble.d
>>
>>- Kris
> 
> 
> [reading dtoa.c]
> 
> "kinda' frigtening" doesn't even begin to describe it.  Not only am I reminded
> of why I switched to D, but I actually feel a touch queasy now.
> 
> Here's to cleaner solutions and better looking code.
> 
> - EricAnderton at yahoo


First time I read through dtoa.c, I was about half way through and thinking "egad! what the feck?" when up pops a comment in the code saying "Now, here's the difficult stuff" ... I knew, at that point, that I was completely out of my depth.
« First   ‹ Prev
1 2