1. 1

This function returns a positive nonzero number if x is negative, and 0 otherwise:

f(x): abs(x) - x

And this one returns a negative number if x is negative, and 0 otherwise:

f(x): x - abs(x)

  1.  

  2. 8

    Instead of “mathematical”, do you mean “arithmetical”? Otherwise, why not use boolean logic? f(c): x < 0

    1. 1

      Actually, you’re right.

    2. 7

      So for the second function to be usable, I have to check if the return value is non-zero… what do I gain from simply checking whether a number is less than zero?

      1. 0

        You decide.

      2. 6

        Both of these functions will return 0 for the minimum value on a fixed-width 2’s complement system.

        Here is a C program to demonstrate these results. Invoking abs on the minimum value is undefined behavior.

        1. 1

          Not if I define abs(x) as pow((x*x), 0.5).

          Here: https://gist.github.com/Unlimiter/a63f67b154f97c2dc12d4679bc73519a

        2. 5

          How do you define abs(x)?

          1. 2

            abs(x) = (x * x) ^ 0.5

            1. 4

              The square root is by Newton’s method or similar?

              I’d imagine floating point has edge cases where this wouldn’t give the right answer.

          2. 3

            This might be useful if you are writing GPU code that avoids branches for performance reasons. Branches can be far more costly on a GPU than they are on a CPU.

            1. 3

              Although this code branches because the abs implementation is usually branching. For example, in glibc it’s implemented as i < 0 ? -i : i

              1. 2

                That may be the default glibc implementation, but if you are writing high performance code, then you will instead be using the builtin abs or fabs intrinsic provided by your compiler, which compiles into the abs instruction provided by your CPU or GPU. For example, GCC has these intrinsics, and Intel has this instruction as part of SSSE3.

            2. 3

              If your language represents booleans as the integers 0 and 1, you can also use this Iversonian phrase:

              (x>0)-(x<0)
              
              1. 4

                Come on that’s just kaomoji

                1. 1

                  I tried to apply that with an arithmetical method.

                2. 2
                  bool notneg(int32_t n) {
                      return (((uint32_t)n) / 0x80000000) == 0;
                  }
                  
                  1. 1

                    That uses a boolean technique (==).

                    1. 2

                      Fixed.

                      #include <stdio.h>
                      #include <stdbool.h>
                      #include <stdint.h>
                      
                      bool notneg(int32_t n) {
                          return 1 - (((uint32_t)n) / 0x80000000);
                      }
                      
                      int main(void) {
                          printf("notneg(0) = %d\n", notneg(0));
                          printf("notneg(1) = %d\n", notneg(1));
                          printf("notneg(500) = %d\n", notneg(500));
                          printf("notneg(0x7FFFFFFF) = %d\n", notneg(0x7FFFFFFF));
                          printf("notneg(-1) = %d\n", notneg(-1));
                          printf("notneg(-500) = %d\n", notneg(-500));   
                          printf("notneg(0x80000000) = %d\n", notneg(0x80000000));
                          return 0;
                      }
                      
                      1. 1

                        Nice. But it uses advantage of int limit (I checked that 0x80000000 == INT_MIN). The main feature of my suggestion is that it should always be general, not just computer-based.

                        1. 3

                          All computers have finite memory, so a trick like this will always be available.

                          Do you have a general solution that doesn’t require floating point numbers to solve integer inputs?

                          1. 1

                            Yes, I wrote a proper version of dbremner’s implementation.

                            1. 3

                              No. Your code clearly uses floating point numbers to solve integer inputs (ie, 0.5 floats).

                              int abs(int i) {
                                return pow((i*i), 0.5);
                              }
                              

                              *edit: Could use something like this

                              #include <stdlib.h>
                              #include <stdio.h>
                              #include <stdint.h>
                              #include <stdbool.h>
                              
                              uint32_t
                              iroot(uint32_t n)
                              {
                                  // UINT32_MAX = 2**32 - 1
                                  for (uint32_t i = 0; i < 65536; ++i) {
                                      if (n == i*i) {
                                          return i;
                                      }
                                  }
                              
                                  return -1;
                              }
                              
                              int
                              main(void)
                              {
                                  printf("iroot(1) = %u\n", iroot(1));
                                  printf("iroot(4) = %u\n", iroot(4));
                                  printf("iroot(9) = %u\n", iroot(9));
                                  printf("iroot(16) = %u\n", iroot(16));
                                  printf("iroot(17) = %u\n", iroot(17));
                                  printf("iroot(225) = %u\n", iroot(225));
                                  printf("iroot(226) = %u\n", iroot(226));
                                  return 0;
                              }
                              
                              1. 1

                                But where is the check for negative integers? iroot doesn’t conclude that n is negative or not.

                  2. 2

                    Not really checking anything as it doesn’t return true/false (1/0).

                    1. 1

                      “arithmetical”. Actually, any number other than 0 is considered true.

                      1. 2

                        Still not really checking, perhaps constraining the values.

                        1. 1

                          Not needed, because, I believe, most PLs work with nonzero numbers as if they were “true” values/booleans in comparison operations.