length's type.

Gary Chike chikega at gmail.com
Wed Feb 7 19:20:12 UTC 2024


On Sunday, 28 January 2024 at 17:25:49 UTC, mw wrote:

> See the result here:
>
> https://forum.dlang.org/post/cagloplexjfzubncxuza@forum.dlang.org

I knew this outlandish output had to do with mixing of signed and 
unsigned types with resulting overflow. But I like the way 
Anthropic Claude2 explains it:

---
The **outlandish output** you're observing in the D code occurs 
due to an **integer overflow**. Let's break down what's happening:

1. **Sum Calculation**:
    - The `sum(elem)` function correctly calculates the sum of all 
elements in the `elem` array, which is **15** (1 + 2 + 3 + 4 + 5).
    - So far, so good!

2. **Average Calculation**:
    - Next, you calculate the average of the `a` array using the 
expression `sum(a) / a.length`.
    - The `sum(a)` part correctly computes the sum of the elements 
in `a`, which is **-5000** (since `-5000 + 0 = -5000`).
    - The issue arises with `a.length`.

3. **Array Length and Unsigned Types**:
    - In D, the `.length` property of an array returns an unsigned 
integer (`ulong`), which is an unsigned 64-bit integer.
    - The length of the `a` array is **2** (since it has two 
elements: -5000 and 0).

4. **Integer Division**:
    - When you perform `sum(a) / a.length`, the division is done 
using integer division rules.
    - The result of `-5000 / 2` is **-2500** (integer division 
truncates the decimal part).

5. **Overflow**:
    - The result of `-2500` is stored in the `c` variable, which 
is of type `ulong`.
    - Since `ulong` is an unsigned type, the value wraps around 
due to overflow.
    - The actual value stored in `c` is **9223372036854773308**, 
which is the result of wrapping around from -2500 to a large 
positive value.

6. **Explanation**:
    - The overflow occurs because `-2500` (as a signed integer) is 
equivalent to a large positive value when interpreted as an 
unsigned 64-bit integer.
    - The result is not what you intended for the average 
calculation.

To fix this, you can explicitly cast the sum to a signed integer 
before dividing to ensure correct behavior:

```d
auto c = cast(double)(sum(a)) / a.length;
```

This will correctly compute the average and prevent overflow. The 
output should now match your expectations! 🚀

The corrected code:
```d
module array_length_forum;

import std.algorithm;
import std.stdio;

void main() {
     auto elem = [1, 2, 3, 4, 5];
     writeln(sum(elem)); // 15 <- // The sum of all the elements 
in the range

     long[]a = [-5000, 0];
     //auto c = sum(a)/a.length;  // length() returns 'ulong', 
inferred as 'ulong'
     auto c = cast(double)(sum(a)) / a.length;
     writeln(typeid(c)); // double
     writeln(c); // -2500 correct output
}
```





More information about the Digitalmars-d-learn mailing list