www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Wrong result with enum

reply Salih Dincer <salihdb hotmail.com> writes:
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
next sibling parent zjh <fqbqrr 163.com> writes:
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
prev sibling next sibling parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
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
parent reply Salih Dincer <salihdb hotmail.com> writes:
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:
 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.
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
next sibling parent reply Tejas <notrealemail gmail.com> writes:
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:
 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.
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)...
Are you on 32-bit OS? I believe `size_t` is 32 bits on 32 bit OS and 64 on a 64-bit OS
Nov 11 2021
parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
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:
 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:
 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.
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)...
Are you on 32-bit OS? I believe `size_t` is 32 bits on 32 bit OS and 64 on a 64-bit OS
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.
Nov 11 2021
prev sibling parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Thursday, 11 November 2021 at 09:11:37 UTC, Salih Dincer wrote:

 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)...
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.
Nov 11 2021
parent Salih Dincer <salihdb hotmail.com> writes:
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:

 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)...
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.
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; } ```
Nov 11 2021
prev sibling next sibling parent Adam D Ruppe <destructionator gmail.com> writes:
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
That's an `int` literal. Try enum wLimit = 100_000L; the L suffix makes a `long` literal.
Nov 11 2021
prev sibling parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
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