Bug 4673 – Bug in std.string (isNumeric)

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2010-08-18T03:08:00Z
Last change time
2015-06-09T05:15:22Z
Assigned to
andrei
Creator
petitv.isat

Attachments

IDFilenameSummaryContent-TypeSize
725facto.dSource code (from description)application/octet-stream582
733isNumeric.dMaybe a patch which works.text/plain3220
740isNumeric.dImprovements of the proposed patchtext/plain2720

Comments

Comment #0 by petitv.isat — 2010-08-18T03:08:20Z
Created attachment 725 Source code (from description) Hi. I was doing some recursivity with D and I probably found a bug with the isNumeric() function. Here's the source code (also in attach) : import std.stdio; import std.string; import std.conv; int main(string[] args) { if(args.length > 1) { int number; foreach(item; args) { if(isNumeric(item)) { number = parse!(uint)(item); // seems to have a bug with 'L' and 'F' values writeln("Facto of ", number, " is ", facto(number)); } } } else { writeln("You must specified a number."); } return 0; } uint facto(uint number) { uint result; if(number <= 1) { result = 1; } else { result = number * facto(number - 1); } return result; } See the result when running the compiled executables with these args : 5 8 A F >facto 5 8 A F Facto of 5 is 120 Facto of 8 is 40320 std.conv.ConError : std.conv(1070) : Can't convert 'F' of type string to type uint It seems that "F" and "L" alone are recognized as Float and Long specifier but ... there's no digit. I accept that 0F, 1L are digits but F and L alone are not.
Comment #1 by bearophile_hugs — 2010-08-18T03:44:53Z
This reduced case shows that parse() doesn't accept "F" or "L", so I don't see the problem yet: import std.conv; void main() { int n1 = parse!uint("F"); int n2 = parse!uint("L"); }
Comment #2 by petitv.isat — 2010-08-18T03:51:37Z
(In reply to comment #1) > This reduced case shows that parse() doesn't accept "F" or "L", so I don't see > the problem yet: > > > import std.conv; > void main() { > int n1 = parse!uint("F"); > int n2 = parse!uint("L"); > } Some changes in your reduced case : import std.conv; import std.string; void main() { if(isNumeric("F")) // isNumeric("F") return True : since when "F" is a numeric ? { int n1 = parse!uint("F"); } if(isNumeric("L")) // same for "L" { int n2 = parse!uint("L"); } if(isNumeric("U")) // same here ... { uint n3 = parse!uint("U"); } }
Comment #3 by bearophile_hugs — 2010-08-18T04:07:13Z
You are right, my reduced version was useless, this shows the problem: import std.string: isNumeric; void main() { assert(isNumeric("F")); assert(isNumeric("L")); assert(isNumeric("U")); }
Comment #4 by kennytm — 2010-08-18T10:33:49Z
(In reply to comment #3) > You are right, my reduced version was useless, this shows the problem: > > import std.string: isNumeric; > void main() { > assert(isNumeric("F")); > assert(isNumeric("L")); > assert(isNumeric("U")); > } The following strings are also wrongly classified as numeric: import std.string; void main () { assert(isNumeric("i")); assert(isNumeric("fi")); assert(isNumeric("ul")); assert(isNumeric("li")); assert(isNumeric(".")); assert(isNumeric("-")); assert(isNumeric("+")); assert(isNumeric("e-")); assert(isNumeric("e+")); assert(isNumeric(".f")); assert(isNumeric("e+f")); }
Comment #5 by petitv.isat — 2010-08-20T14:06:05Z
Created attachment 733 Maybe a patch which works. Well this is way to improve the current isNumeric function. It works well for these kinds of numerics : (+/-) 1, 1L, 1UL, 1i, 1Fi, 1Li, 1F 1.55 1e+52 1_500_250 nan, nani, nan+nani (+/-) inf At least, this patch correct bugs found in the std.isNumeric function. Sure we can (should !) improve it but at least it works (except for numerics like .5e-52 but 0.5e-52 works)
Comment #6 by kennytm — 2010-08-20T14:13:56Z
Should complex literals ("3.4+5.6i") _still_ be considered numeric? As the built-in complex types are scheduled for deprecation...
Comment #7 by issues.dlang — 2010-08-20T14:42:21Z
I though that they were doing the same with complex numbers that they did with associative arrays, which was to remove it from the language itself but have the compiler use a library solution for it (kind of like it using the object module with Object in it rather than just knowing the definition). So, the syntax would be the same, but how it would be dealt with internally would be different. I could be wrong on that though.
Comment #8 by petitv.isat — 2010-08-25T10:52:47Z
Created attachment 740 Improvements of the proposed patch Well, I checked the lexical page about D2 and it seems that something like 1_2_3_4_5_._5_4e-5_2_ is a numeric, so I decided to make some changes to the regex to allow this kind of numerics. But I wonder, should we consider hex things like 0xFFF as numerics or should we have to make another function like "isHexadecimal" ?
Comment #9 by kennytm — 2010-08-25T12:31:06Z
(In reply to comment #8) > Created an attachment (id=740) [details] > Improvements of the proposed patch > > Well, I checked the lexical page about D2 and it seems that something like > 1_2_3_4_5_._5_4e-5_2_ is a numeric, so I decided to make some changes to the > regex to allow this kind of numerics. > > But I wonder, should we consider hex things like 0xFFF as numerics or should we > have to make another function like "isHexadecimal" ? The current isNumeric function also considered "123,456,789" numeric (with the bAllowSep parameter set to true). May be there should be another function or switch that handles "human-readable numeric string" and "number literals in D syntax" differently.
Comment #10 by alanb — 2013-09-03T16:38:06Z
isNumeric still thinks strings containing only "-" "+" and "." are numeric. Here is a related bug report with additional thoughts and a suggestion that the conversion library should add a function to check if a given conversion will succeed or not. http://d.puremagic.com/issues/show_bug.cgi?id=3610 If isNumeric won't be fixed, then it should be depreciated rather than keep it broken in the library. --rt
Comment #11 by github-bugzilla — 2013-12-27T15:15:50Z