digitalmars.D.learn - Wrong result with enum
- Salih Dincer (29/29) Nov 10 2021 is this a issue, do you need to case?
- zjh (2/3) Nov 10 2021 out of bound.
- Stanislav Blinov (4/9) Nov 10 2021 https://dlang.org/spec/enum.html#named_enums
- Salih Dincer (10/21) Nov 11 2021 100001
- Tejas (3/26) Nov 11 2021 Are you on 32-bit OS? I believe `size_t` is 32 bits on 32 bit OS
- Patrick Schluter (6/33) Nov 11 2021 That's not the issue with his code. The 32 bit overflow happens
- Stanislav Blinov (10/20) Nov 11 2021 That code is
- Salih Dincer (18/39) Nov 11 2021 Thank you all :)
- Adam D Ruppe (4/8) Nov 11 2021 That's an `int` literal. Try
- Patrick Schluter (9/38) Nov 11 2021 Integer overflow. By default an enum is defined as `int` which is
is this a issue, do you need to case? ```d enum tLimit = 10_000; // (1) true result enum wLimit = 100_000; // (2) wrong result void main() { size_t subTest1 = tLimit; assert(subTest1 == tLimit); /* no error */ size_t subTest2 = wLimit; assert(subTest2 == wLimit); /* no error */ size_t gauss = (tLimit * (tLimit + 1)) / 2; assert(gauss == 50_005_000); /* no error */ gauss = (wLimit * (wLimit + 1)) / 2; assert(gauss == 5_000_050_000); /* failure // Fleeting Solution: enum size_t limit = 100_000; gauss = (limit * (limit + 1)) / 2; assert(gauss == 5_000_050_000); //* no error */ } /* Small Version: void main(){ enum t = 10_000; size_t a = t * t; assert(a == 100_000_000); // No Error enum w = 100_000; size_t b = w * w; assert(b == 10_000_000_000); // Assert Failure } */ ```
Nov 10 2021
On Thursday, 11 November 2021 at 05:37:05 UTC, Salih Dincer wrote:is this a issue, do you need to case?out of bound.
Nov 10 2021
On Thursday, 11 November 2021 at 05:37:05 UTC, Salih Dincer wrote:is this a issue, do you need to case? ```d enum tLimit = 10_000; // (1) true result enum wLimit = 100_000; // (2) wrong result ```https://dlang.org/spec/enum.html#named_enums Unless explicitly set, default type is int. 10000100000 is greater than int.max.
Nov 10 2021
On Thursday, 11 November 2021 at 06:34:16 UTC, Stanislav Blinov wrote:On Thursday, 11 November 2021 at 05:37:05 UTC, Salih Dincer wrote:100001 ```d enum w = 100_000; size_t b = w * w; // size_t b = 100000 * 100000; // ??? assert(b == 10_000_000_000); // Assert Failure ``` The w!(int) is not greater than the b!(size_t)...is this a issue, do you need to case? ```d enum tLimit = 10_000; // (1) true result enum wLimit = 100_000; // (2) wrong result ```https://dlang.org/spec/enum.html#named_enums Unless explicitly set, default type is int. 10000100000 is greater than int.max.
Nov 11 2021
On Thursday, 11 November 2021 at 09:11:37 UTC, Salih Dincer wrote:On Thursday, 11 November 2021 at 06:34:16 UTC, Stanislav Blinov wrote:Are you on 32-bit OS? I believe `size_t` is 32 bits on 32 bit OS and 64 on a 64-bit OSOn Thursday, 11 November 2021 at 05:37:05 UTC, Salih Dincer wrote:100001 ```d enum w = 100_000; size_t b = w * w; // size_t b = 100000 * 100000; // ??? assert(b == 10_000_000_000); // Assert Failure ``` The w!(int) is not greater than the b!(size_t)...is this a issue, do you need to case? ```d enum tLimit = 10_000; // (1) true result enum wLimit = 100_000; // (2) wrong result ```https://dlang.org/spec/enum.html#named_enums Unless explicitly set, default type is int. 10000100000 is greater than int.max.
Nov 11 2021
On Thursday, 11 November 2021 at 12:05:19 UTC, Tejas wrote:On Thursday, 11 November 2021 at 09:11:37 UTC, Salih Dincer wrote:That's not the issue with his code. The 32 bit overflow happens already during the `w * w` mulitplication. The wrong result is then assigned to the `size_t`. `cast(size_t)w * w` or the declaration `enum : size_t { w = 100_000 };` would change that.On Thursday, 11 November 2021 at 06:34:16 UTC, Stanislav Blinov wrote:Are you on 32-bit OS? I believe `size_t` is 32 bits on 32 bit OS and 64 on a 64-bit OSOn Thursday, 11 November 2021 at 05:37:05 UTC, Salih Dincer wrote:100001 ```d enum w = 100_000; size_t b = w * w; // size_t b = 100000 * 100000; // ??? assert(b == 10_000_000_000); // Assert Failure ``` The w!(int) is not greater than the b!(size_t)...is this a issue, do you need to case? ```d enum tLimit = 10_000; // (1) true result enum wLimit = 100_000; // (2) wrong result ```https://dlang.org/spec/enum.html#named_enums Unless explicitly set, default type is int. 10000100000 is greater than int.max.
Nov 11 2021
On Thursday, 11 November 2021 at 09:11:37 UTC, Salih Dincer wrote:That code is ``` size_t b = int(w) * int(w); ``` That is, `multiply two ints and assign result to a size_t`. Multiplication of two ints is still an int though, and you can't fit ten billion in an int, so that's overflow. It doesn't matter that you declare `b` as `size_t` here. Overflow happens before that assignment.Unless explicitly set, default type is int. 10000100000 is greater than int.max.100001 ```d enum w = 100_000; size_t b = w * w; // size_t b = 100000 * 100000; // ??? assert(b == 10_000_000_000); // Assert Failure ``` The w!(int) is not greater than the b!(size_t)...
Nov 11 2021
On Thursday, 11 November 2021 at 14:52:45 UTC, Stanislav Blinov wrote:On Thursday, 11 November 2021 at 09:11:37 UTC, Salih Dincer wrote:Thank you all :) DMD still has to type inference... I think the safest and most practical method is to explicitly use double types: ```d import std.stdio; enum factors { n = 1e+9, n1 } auto gauss (double a = factors.n, double b = factors.n1) { return cast(size_t)(a * b)/2; } void main() { gauss.writeln; ulong.max.writeln; } ```That code is ``` size_t b = int(w) * int(w); ``` That is, `multiply two ints and assign result to a size_t`. Multiplication of two ints is still an int though, and you can't fit ten billion in an int, so that's overflow. It doesn't matter that you declare `b` as `size_t` here. Overflow happens before that assignment.Unless explicitly set, default type is int. 10000100000 is greater than int.max.100001 ```d enum w = 100_000; size_t b = w * w; // size_t b = 100000 * 100000; // ??? assert(b == 10_000_000_000); // Assert Failure ``` The w!(int) is not greater than the b!(size_t)...
Nov 11 2021
On Thursday, 11 November 2021 at 05:37:05 UTC, Salih Dincer wrote:is this a issue, do you need to case? ```d enum tLimit = 10_000; // (1) true result enum wLimit = 100_000; // (2) wrong resultThat's an `int` literal. Try enum wLimit = 100_000L; the L suffix makes a `long` literal.
Nov 11 2021
On Thursday, 11 November 2021 at 05:37:05 UTC, Salih Dincer wrote:is this a issue, do you need to case? ```d enum tLimit = 10_000; // (1) true result enum wLimit = 100_000; // (2) wrong result void main() { size_t subTest1 = tLimit; assert(subTest1 == tLimit); /* no error */ size_t subTest2 = wLimit; assert(subTest2 == wLimit); /* no error */ size_t gauss = (tLimit * (tLimit + 1)) / 2; assert(gauss == 50_005_000); /* no error */ gauss = (wLimit * (wLimit + 1)) / 2; assert(gauss == 5_000_050_000); /* failure // Fleeting Solution: enum size_t limit = 100_000; gauss = (limit * (limit + 1)) / 2; assert(gauss == 5_000_050_000); //* no error */ } /* Small Version: void main(){ enum t = 10_000; size_t a = t * t; assert(a == 100_000_000); // No Error enum w = 100_000; size_t b = w * w; assert(b == 10_000_000_000); // Assert Failure } */ ```Integer overflow. By default an enum is defined as `int` which is limited to 32 bit. `int.max` is 2_147_483_647 which is the biggest number representable with an int. You can declare the enum to be of a bigger type `enum : long { w = 100_000 };` or you can use `std.bigint` if you don't know the maximum you work with or the library `std.experimental.checkedint` which allows to set the behaviour one wants in case of overflow.
Nov 11 2021