3 ms·
The negative sign doesn't save you. `ii` takes every value in [0,len), so as soon as `ii` gets to `len/2 + 1` the unsigned subtraction became `2^64 - 1` (18446
by xscott 5y ago
The negative sign doesn't save you. `ii` takes every value in [0,len), so as soon as `ii` gets to `len/2 + 1` the unsigned subtraction became `2^64 - 1` (18446744073709551615), quietly converted/rounded to a pretty big double (18446744073709551616.0), and gave you the wrong answer without even a compiler warning.
You're proving my point :-)
> (Assuming my guesses about the intended behaviour and the types of data/sinc/etc are correct.)
I probably should've specified that, but I'm too verbose as is. I intended `data` as an array of doubles, and `sinc` is a function that returns a double. Change `sinc` to `sin` or `cos` if it helps to think about it.
> idiomatic (so admittedly non-obvious) reverse loops
Heh, I've only seen that as a joke where people call `-->` the "goes to operator". It's not an idiom I'm eager to embrace. I think some people like:
for (size_t ii = len-1; ii != SIZE_MAX; ii--)
I'm not a fan of that one.
- a1369209993 5y ago> [for odd len] as soon as `ii` gets to `len/2 + 1` the unsigned subtraction became `2^64 - 1` That's actually a completely different problem, namely my tendency to mistake x/2 as rounding up rather than down. The original code generates sinc(+scale) on the last element of a odd-length array, rather than sinc(0). (So apparently my guess that the original had a bug was correct, it just wasn't the negative multiples. Admittedly, I should have caught that immediately from the fact that it aligns the zero point to the end of the array rather than the beginning.) Correct code would be: double scale = <non-integer value>; for(size_t ii=0; ii<len ;ii++) { data[ii] = sinc(-scale*((len+1)/2-ii)); } This reinforces my belief that unsigned integers are preferable: they (occasionally) make off-by-one errors explode loudly rather than quietly producing subtle rounding and (visual/audio) alignment issues.
- xscott 5y ago> Correct code would be: ... Nah, it's still really broken :-) Here, let's take all the confusing stuff out - no arrays, sinc functions, etc.. This compiles cleanly with -Wall and -Wextra #include <stdio.h> int main() { size_t len = 6; double scale = 0.1; for(size_t ii=0; ii<len ;ii++) { printf("%.2lf\n", -scale*((len+1)/2-ii)); } } Using size_t, it prints: -0.30 -0.20 -0.10 -0.00 -1844674407370955264.00 -1844674407370955264.00 If you change it to use to `ssize_t`, you get the desired result: -0.30 -0.20 -0.10 -0.00 0.10 0.20 > This reinforces my belief that unsigned integers [...] I hope to show you that's wrong :-) > they (occasionally) make off-by-one errors explode loudly The problem isn't an off-by-one error, it's unsigned underflow.