Thread overview
Wrong result with enum
Nov 11, 2021
Salih Dincer
Nov 11, 2021
zjh
Nov 11, 2021
Stanislav Blinov
Nov 11, 2021
Salih Dincer
Nov 11, 2021
Tejas
Nov 11, 2021
Patrick Schluter
Nov 11, 2021
Stanislav Blinov
Nov 12, 2021
Salih Dincer
Nov 11, 2021
Adam D Ruppe
Nov 11, 2021
Patrick Schluter
November 11, 2021

is this a issue, do you need to case?

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
}
*/
November 11, 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.

November 11, 2021

On Thursday, 11 November 2021 at 05:37:05 UTC, Salih Dincer wrote:

>

is this a issue, do you need to case?

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.

November 11, 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:

>

is this a issue, do you need to case?

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

  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)...

November 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:

>

On Thursday, 11 November 2021 at 05:37:05 UTC, Salih Dincer wrote:

>

is this a issue, do you need to case?

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

  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

November 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:

>

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?

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

  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.

November 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


That's an `int` literal. Try

enum wLimit = 100_000L;

the L suffix makes a `long` literal.
November 11, 2021

On Thursday, 11 November 2021 at 05:37:05 UTC, Salih Dincer wrote:

>

is this a issue, do you need to case?

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.

November 11, 2021

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

  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.

November 12, 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:

> >

Unless explicitly set, default type is int. 10000100000 is greater than int.max.
100001

  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:

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;
}