www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Bug? 0 is less than -10

reply tcak <1ltkrs+3wyh1ow7kzn1k sharklasers.com> writes:
Maybe I am just too stressed out to see the problem.

[code]
import std.stdio;

void main(){
	size_t dec = 0;

	writeln( dec, " ", (dec <= -10), " ", (dec >= 10), " ", ((dec <= 
-10) || (dec >= 10)) );
}
[/code]

[output]
0 true false true
[/output]

How is it generating "true" for (dec <= -10) ? Is there a special 
casting or something?

DMD 2.068.2, Ubuntu 64-bit
Oct 06 2015
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 6 October 2015 at 14:46:56 UTC, tcak wrote:
 void main(){
 	size_t dec = 0;
 How is it generating "true" for (dec <= -10) ? Is there a 
 special casting or something?
size_t is unsigned, so the -10 is cast to unsigned too for the comparison which yields some huge number. Comparing signed to unsigned is almost always a mistake... but one D inherited from C. This is a reason why I prefer to use int instead of size_t where I can but that might require casts and truncation too.
Oct 06 2015
parent reply Laeeth Isharc <spamnolaeeth nospamlaeeth.com> writes:
On Tuesday, 6 October 2015 at 14:55:23 UTC, Adam D. Ruppe wrote:
 On Tuesday, 6 October 2015 at 14:46:56 UTC, tcak wrote:
 void main(){
 	size_t dec = 0;
 How is it generating "true" for (dec <= -10) ? Is there a 
 special casting or something?
size_t is unsigned, so the -10 is cast to unsigned too for the comparison which yields some huge number. Comparing signed to unsigned is almost always a mistake... but one D inherited from C. This is a reason why I prefer to use int instead of size_t where I can but that might require casts and truncation too.
could we have ssize_t defined in phobos somewhere so your code ends up being portable ;) (It's trivial to do, obviously).
Oct 06 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 10/6/15 7:21 PM, Laeeth Isharc wrote:
 could we have ssize_t defined in phobos somewhere so your code ends up
 being portable ;) (It's trivial to do, obviously).
ptrdiff_t -Steve
Oct 06 2015
parent reply Laeeth Isharc <laeethnospam nospam.laeeth.com> writes:
On Wednesday, 7 October 2015 at 02:53:32 UTC, Steven 
Schveighoffer wrote:
 On 10/6/15 7:21 PM, Laeeth Isharc wrote:
 could we have ssize_t defined in phobos somewhere so your code 
 ends up
 being portable ;) (It's trivial to do, obviously).
ptrdiff_t -Steve
It seems unnatural to use such a name when the variable has nothing to do with pointers - it doesn't contribute to the readability. Yes, it's trivial, but small things cumulatively matter. Adam tends to use int and when that gets mixed up with an auto size_t (eg via length) then his code doesn't compile on 64 bit. And if it happens with his code, you can imagine this isn't a problem that inexperienced users never encounter.
Oct 06 2015
next sibling parent reply Andrea Fontana <nospam example.com> writes:
On Wednesday, 7 October 2015 at 05:27:12 UTC, Laeeth Isharc wrote:
 On Wednesday, 7 October 2015 at 02:53:32 UTC, Steven 
 Schveighoffer wrote:
 On 10/6/15 7:21 PM, Laeeth Isharc wrote:
 could we have ssize_t defined in phobos somewhere so your 
 code ends up
 being portable ;) (It's trivial to do, obviously).
ptrdiff_t -Steve
It seems unnatural to use such a name when the variable has nothing to do with pointers - it doesn't contribute to the readability. Yes, it's trivial, but small things cumulatively matter. Adam tends to use int and when that gets mixed up with an auto size_t (eg via length) then his code doesn't compile on 64 bit. And if it happens with his code, you can imagine this isn't a problem that inexperienced users never encounter.
IMO it seems unnatural to use size_t with a signed/negative value too.
Oct 07 2015
parent Laeeth Isharc <laeethnospam nospam.laeeth.com> writes:
On Wednesday, 7 October 2015 at 07:38:44 UTC, Andrea Fontana 
wrote:
 On Wednesday, 7 October 2015 at 05:27:12 UTC, Laeeth Isharc 
 wrote:
 On Wednesday, 7 October 2015 at 02:53:32 UTC, Steven 
 Schveighoffer wrote:
 On 10/6/15 7:21 PM, Laeeth Isharc wrote:
 could we have ssize_t defined in phobos somewhere so your 
 code ends up
 being portable ;) (It's trivial to do, obviously).
ptrdiff_t -Steve
It seems unnatural to use such a name when the variable has nothing to do with pointers - it doesn't contribute to the readability. Yes, it's trivial, but small things cumulatively matter. Adam tends to use int and when that gets mixed up with an auto size_t (eg via length) then his code doesn't compile on 64 bit. And if it happens with his code, you can imagine this isn't a problem that inexperienced users never encounter.
IMO it seems unnatural to use size_t with a signed/negative value too.
Indeed. But you end up with an inferred size_t in a foreach and using length with auto, so it makes sense to have something nicer that you can specify that won't make your code look strange. Doesn't bother me since I define ssize_t, but it might make D easier to read for others. When you see ptrdiff_t with no pointer in sight it's not very clear unless you are familiar with C idioms (and I never remember seeing this back when I learnt C - some modern thing).
Oct 07 2015
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 10/7/15 1:27 AM, Laeeth Isharc wrote:
 On Wednesday, 7 October 2015 at 02:53:32 UTC, Steven Schveighoffer wrote:
 On 10/6/15 7:21 PM, Laeeth Isharc wrote:
 could we have ssize_t defined in phobos somewhere so your code ends up
 being portable ;) (It's trivial to do, obviously).
ptrdiff_t
It seems unnatural to use such a name when the variable has nothing to do with pointers - it doesn't contribute to the readability. Yes, it's trivial, but small things cumulatively matter. Adam tends to use int and when that gets mixed up with an auto size_t (eg via length) then his code doesn't compile on 64 bit. And if it happens with his code, you can imagine this isn't a problem that inexperienced users never encounter.
ptrdiff_t is in the C spec, ssize_t is not. No reason to name all the types of snow here. A machine-word-sized signed integer is ptrdiff_t. -Steve
Oct 08 2015
parent Laeeth Isharc <laeethnospam nospamlaeeth.com> writes:
On Thursday, 8 October 2015 at 13:32:17 UTC, Steven Schveighoffer 
wrote:
 On 10/7/15 1:27 AM, Laeeth Isharc wrote:
 On Wednesday, 7 October 2015 at 02:53:32 UTC, Steven 
 Schveighoffer wrote:
 On 10/6/15 7:21 PM, Laeeth Isharc wrote:
 could we have ssize_t defined in phobos somewhere so your 
 code ends up
 being portable ;) (It's trivial to do, obviously).
ptrdiff_t
It seems unnatural to use such a name when the variable has nothing to do with pointers - it doesn't contribute to the readability. Yes, it's trivial, but small things cumulatively matter. Adam tends to use int and when that gets mixed up with an auto size_t (eg via length) then his code doesn't compile on 64 bit. And if it happens with his code, you can imagine this isn't a problem that inexperienced users never encounter.
ptrdiff_t is in the C spec, ssize_t is not. No reason to name all the types of snow here. A machine-word-sized signed integer is ptrdiff_t. -Steve
Whatever - it's not that important to me. D isn't C, and has learnt from C's mistakes and infelicities. I love the beauty of C, but I'm glad I don't need to do my work in it. One reason why D is under appreciated is that these seemingly small differences make a big difference in practice, even if in theory they shouldn't. Initially I was quite offended by no loop aliasing. Until I saw how much time it saved me in avoiding silly mistakes. But really there are better things to worry about at the moment. Laeeth.
Oct 08 2015
prev sibling next sibling parent anonymous <anonymous example.com> writes:
On Tuesday, 6 October 2015 at 14:46:56 UTC, tcak wrote:
 Maybe I am just too stressed out to see the problem.

 [code]
 import std.stdio;

 void main(){
 	size_t dec = 0;

 	writeln( dec, " ", (dec <= -10), " ", (dec >= 10), " ", ((dec 
 <= -10) || (dec >= 10)) );
 }
 [/code]

 [output]
 0 true false true
 [/output]

 How is it generating "true" for (dec <= -10) ? Is there a 
 special casting or something?

 DMD 2.068.2, Ubuntu 64-bit
dec is a size_t. size_t is unsigned. -10 is cast to unsigned for the comparison, resulting in some huge value.
Oct 06 2015
prev sibling next sibling parent Meta <jared771 gmail.com> writes:
On Tuesday, 6 October 2015 at 14:46:56 UTC, tcak wrote:
 Maybe I am just too stressed out to see the problem.

 [code]
 import std.stdio;

 void main(){
 	size_t dec = 0;

 	writeln( dec, " ", (dec <= -10), " ", (dec >= 10), " ", ((dec 
 <= -10) || (dec >= 10)) );
 }
 [/code]

 [output]
 0 true false true
 [/output]

 How is it generating "true" for (dec <= -10) ? Is there a 
 special casting or something?

 DMD 2.068.2, Ubuntu 64-bit
If you need to mix signed and unsigned values but want to avoid this issue, you an use the comparison functions from std.functional.
Oct 06 2015
prev sibling parent reply Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Tuesday, 6 October 2015 at 14:46:56 UTC, tcak wrote:
 Maybe I am just too stressed out to see the problem.

 [code]
 import std.stdio;

 void main(){
 	size_t dec = 0;

 	writeln( dec, " ", (dec <= -10), " ", (dec >= 10), " ", ((dec 
 <= -10) || (dec >= 10)) );
 }
 [/code]

 [output]
 0 true false true
 [/output]

 How is it generating "true" for (dec <= -10) ? Is there a 
 special casting or something?

 DMD 2.068.2, Ubuntu 64-bit
Lionello Lunesu posted a PR that should fix this: https://github.com/D-Programming-Language/dmd/pull/1913 See also the discussion in the linked bug report. Unfortunately it seems it's been forgotten since then...
Oct 07 2015
parent reply Dominikus Dittes Scherkl <Dominikus.Scherkl continental-corporation.com> writes:
On Wednesday, 7 October 2015 at 16:25:02 UTC, Marc Schütz wrote:
 Lionello Lunesu posted a PR that should fix this:
 https://github.com/D-Programming-Language/dmd/pull/1913
 See also the discussion in the linked bug report.

 Unfortunately it seems it's been forgotten since then...
to use less casts: int opCmp(T, U)(const(T) a, const(U) b) pure safe nogc nothrow if(isIntegral!T && isIntegral!U && !is(Unqual!T == Unqual!U)) { static if(isSigned!T && isUnsigned!U && T.sizeof <= U.sizeof) { return (a < 0) ? -1 : opCmp(cast(U)a, b); } else static if(isUnsigned!T && isSigned!U && T.sizeof >= U.sizeof) { return (b < 0) ? 1 : opCmp(a, cast(T)b); } else // both signed or both unsigned or the unsigned type is smaller { // do what the compiler always did so far: alias C = CommonType!(T, U); // use the larger of the both return opCmp(cast(C)a, cast(C)b); } } And on comparison with number literals everything will be optimized away, so no execution timer overhead at all!
Oct 08 2015
parent Ozan <ozan.sueel gmail.com> writes:
On Thursday, 8 October 2015 at 09:01:32 UTC, Dominikus Dittes 
Scherkl wrote:
 On Wednesday, 7 October 2015 at 16:25:02 UTC, Marc Schütz wrote:
 Lionello Lunesu posted a PR that should fix this:
 https://github.com/D-Programming-Language/dmd/pull/1913
 See also the discussion in the linked bug report.

 Unfortunately it seems it's been forgotten since then...
Meanwhile I have even improved my solution posted to fix bug int opCmp(T, U)(const(T) a, const(U) b) pure safe nogc nothrow if(isIntegral!T && isIntegral!U && !is(Unqual!T == Unqual!U)) { static if(isSigned!T && isUnsigned!U && T.sizeof <= U.sizeof)
...
 And on comparison with number literals everything will be 
 optimized away, so no execution timer overhead at all!
I like your solution! +1
Oct 09 2015