Did I miss something? I got to the end and still don't know what -n % n actually accomplishes in practice, nor why it's mainly used in high-performance code
What the heck is the value of “-n % n” in programming languages?
11–20 of 30 posts
Re: What the heck is the value of “-n % n” in programming languages?
#12First it's important to note that `n` is unsigned; if it's signed the value of `-n % n` is 0, intuitively. For unsigned n, the value is: MAX - n + 1 (where max is the maximum representable value in the type of n, e.g., UINT_MAX). The article explains this nicely. (I thought of 2's complement when reasoning through this, but you don't actually need to assume 2's complement to follow the reasoning). So, `-n % n` comput…
-n % n (where n is unsigned) suffers from the problem that -n calculates a two's complement. That value is implementation-defined, due to the implementation-defined width of the unsigned type. It's calculating ((-n) mod (2^bits)) mod n, where bits is compiler/platform-dependent. ;; TXR Lisp 1> (defun -n%n (n bits) (mod (mod (- n) (expt 2 bits)) n)) -n%n 2> (-n%n 7 8) 4 3> (-n%n 7 16) 2 4> (-n%n 7 17) 4 5> (-n%n 7 18)…
Re: What the heck is the value of “-n % n” in programming languages?
#13Apart from the overall oddness of this, the result of applying the modulo operator to signed arguments is technically undefined behavior in C.
Re: What the heck is the value of “-n % n” in programming languages?
#14That being said I am not sure I've ever programmed a one's complement machine.
Re: What the heck is the value of “-n % n” in programming languages?
#15 let threshold = (0 &- range) % range
> It is somewhat inconvenient that Swift forces us to write so much code, but we must admit that the result is probably less likely to confuse a good programmer.Oh come on, it's basically just one extra character.
Re: What the heck is the value of “-n % n” in programming languages?
#16Apart from the overall oddness of this, the result of applying the modulo operator to signed arguments is technically undefined behavior in C.
This isn't correct, section 6.5.5 states merely that "The operands of the % operator shall have integer type."
Re: What the heck is the value of “-n % n” in programming languages?
#17int main(void) { unsigned int n = 7; printf("%i", (-n % n)); return 0; } this gives 4 :(
Re: What the heck is the value of “-n % n” in programming languages?
#18First it's important to note that `n` is unsigned; if it's signed the value of `-n % n` is 0, intuitively. For unsigned n, the value is: MAX - n + 1 (where max is the maximum representable value in the type of n, e.g., UINT_MAX). The article explains this nicely. (I thought of 2's complement when reasoning through this, but you don't actually need to assume 2's complement to follow the reasoning). So, `-n % n` comput…
-n % n (where n is unsigned) suffers from the problem that -n calculates a two's complement. That value is implementation-defined, due to the implementation-defined width of the unsigned type. It's calculating ((-n) mod (2^bits)) mod n, where bits is compiler/platform-dependent. ;; TXR Lisp 1> (defun -n%n (n bits) (mod (mod (- n) (expt 2 bits)) n)) -n%n 2> (-n%n 7 8) 4 3> (-n%n 7 16) 2 4> (-n%n 7 17) 4 5> (-n%n 7 18)…
Re: What the heck is the value of “-n % n” in programming languages?
#19> warning C4146: unary minus operator applied to unsigned type, result still unsigned #ifdef _MSVC x = ~x + 1; // "Manual" two's complement to avoid warning. #else x = -x; // Regular two's complement any good C coder knows #endif
Re: What the heck is the value of “-n % n” in programming languages?
#20Earlier quoted context omitted.
-n % n (where n is unsigned) suffers from the problem that -n calculates a two's complement. That value is implementation-defined, due to the implementation-defined width of the unsigned type. It's calculating ((-n) mod (2^bits)) mod n, where bits is compiler/platform-dependent. ;; TXR Lisp 1> (defun -n%n (n bits) (mod (mod (- n) (expt 2 bits)) n)) -n%n 2> (-n%n 7 8) 4 3> (-n%n 7 16) 2 4> (-n%n 7 17) 4 5> (-n%n 7 18)…
Woah, there's even a scary gotcha for types that aren't unsigned. E.g., check out what happens with "unsigned short": https://gcc.godbolt.org/z/4xWo1G . It looks like -n is implicitly converted (to signed int, maybe?) so unless you explicitly re-cast it to "unsigned short", you get something unexpected.
An example where unsigned short promotes to unsigned int are platforms where sizeof(short) == sizeof(int). E.g. 16 bit systems where short and int is 16 bits, and long is 32: compilers for 8086 and such.
If the promotion goes to int, the subsequent - is safe; there is no way the resulting value can be that problematic most negative int of two's complement.
On two's complement systems, even if the - is signed, if you convert the value back to unsigned short, you will get the two's complement value, as if the calculation was done in the unsigned type all along.
For instance a 16 bit unsigned short value of 65535 (0xFFFF) will go to 65535 of type int, which will go to -65535, which will then map to 1 if converted to unsigned short.