digitalmars.D - "Unsigned-related bugs never occur in real code."
- Andrei Alexandrescu (21/21) Jan 20 2010 "It's an academic problem. Don't worry about it and move on."
- bearophile (10/11) Jan 21 2010 Unsigned numbers are evil (especially if you use them in a language with...
- bearophile (3/3) Jan 21 2010 And abs() of an unsigned number probably needs a compilation warning.
- Don (2/3) Jan 21 2010 Not a warning, it's always an error.
- Andrei Alexandrescu (3/7) Jan 21 2010 Ok, makes sense. I'll operate the change in Phobos.
- Rainer Deyke (5/9) Jan 21 2010 I can imagine abs(x) being useful in a generic function where x can be
- Andrei Alexandrescu (9/16) Jan 21 2010 std.traits has a Unsigned template. I plan to add two functions:
- Rainer Deyke (16/22) Jan 21 2010 It would also be completely and utterly wrong. The correct replacement
- Andrei Alexandrescu (3/26) Jan 21 2010 Depends! In my case, your fix is wrong.
"It's an academic problem. Don't worry about it and move on." That's what Walter kept on telling me. Yet I've spent the better part of an hour reducing a bug down to the following: import std.math, std.stdio; void main() { auto a = [ 4, 4, 2, 3, 2 ]; float avgdist = 0; uint count; foreach (i, e1; a) { foreach (j, e2; a) { if (i == j) continue; if (e1 != e2) continue; ++count; avgdist += abs(i - j); } } writeln(count, " ", avgdist / count); } May this post be an innocent victim of the war against unsigned-related bugs. Andrei
Jan 20 2010
Andrei Alexandrescu:May this post be an innocent victim of the war against unsigned-related bugs.<Unsigned numbers are evil (especially if you use them in a language with no integral overflow tests). A partial solution to this problem is: 1) to use them in a program only where you really need them, for example as bitfields or as an optimization, etc (this can be done in D1 too); 2) to have compile-time & run-time integral overflow tests active by default unless they are disabled with a compiler command line argument, as in Delphi, 4) to use more unit tests, every little piece of code you write has to be tested. And adding invariants along the way in your computations is positive (this can be done in D1 too); 3) to replace size_t with ptrdiff_t everywhere in the language and standard library, unless really needed (so those i and j are signed integers by default, array.length returns a signed value, array slicing and indexes have a signed value argument, etc) (I think this can't be done in D1). Doing those three things is not going to solve the problem fully, but it will reduce the bug count in D programs. (Once that's done I'd like to see how many bugs it catches in the std lib, and other libs & programs already written). A better solution is the one I've explained in the comments about Guy Steele. Fixed-sized numbers (even with overflow tests) are necessary for performance and I want them available where I need more performance, to me but they look more and more like a premature optimization. Bye, bearophile
Jan 21 2010
And abs() of an unsigned number probably needs a compilation warning. Bye, bearophile
Jan 21 2010
bearophile wrote:And abs() of an unsigned number probably needs a compilation warning.Not a warning, it's always an error.
Jan 21 2010
Don wrote:bearophile wrote:Ok, makes sense. I'll operate the change in Phobos. AndreiAnd abs() of an unsigned number probably needs a compilation warning.Not a warning, it's always an error.
Jan 21 2010
Don wrote:bearophile wrote:I can imagine abs(x) being useful in a generic function where x can be either signed or unsigned. -- Rainer Deyke - rainerd eldwood.comAnd abs() of an unsigned number probably needs a compilation warning.Not a warning, it's always an error.
Jan 21 2010
Rainer Deyke wrote:Don wrote:std.traits has a Unsigned template. I plan to add two functions: signed(x) and unsigned(x), which transform the integral x into the signed/unsigned integral of the same size. Generic code could then call signed or unsigned wherever necessary. For abs, they'd have to call abs(signed(expr)) which I believe clarifies intent and averts bugs like mine. Alas, that's not fixing everything... Andreibearophile wrote:I can imagine abs(x) being useful in a generic function where x can be either signed or unsigned.And abs() of an unsigned number probably needs a compilation warning.Not a warning, it's always an error.
Jan 21 2010
Andrei Alexandrescu wrote:std.traits has a Unsigned template. I plan to add two functions: signed(x) and unsigned(x), which transform the integral x into the signed/unsigned integral of the same size. Generic code could then call signed or unsigned wherever necessary. For abs, they'd have to call abs(signed(expr)) which I believe clarifies intent and averts bugs like mine.It would also be completely and utterly wrong. The correct replacement is this: T result; if (isSigned!T) { result = abs(v); } else { result = v; } ...which works, but is a lot less concise than simply saying 'v = abs(v)'. If I ever found myself writing the above in actual code, I'd be tempted to factor it out into its own function, call that function 'abs', and consistently use that function instead of the 'abs' in Phobos. -- Rainer Deyke - rainerd eldwood.com
Jan 21 2010
Rainer Deyke wrote:Andrei Alexandrescu wrote:Depends! In my case, your fix is wrong. Andreistd.traits has a Unsigned template. I plan to add two functions: signed(x) and unsigned(x), which transform the integral x into the signed/unsigned integral of the same size. Generic code could then call signed or unsigned wherever necessary. For abs, they'd have to call abs(signed(expr)) which I believe clarifies intent and averts bugs like mine.It would also be completely and utterly wrong. The correct replacement is this: T result; if (isSigned!T) { result = abs(v); } else { result = v; } ....which works, but is a lot less concise than simply saying 'v = abs(v)'. If I ever found myself writing the above in actual code, I'd be tempted to factor it out into its own function, call that function 'abs', and consistently use that function instead of the 'abs' in Phobos.
Jan 21 2010