absolute value of difference between 2 chars in ASCII table without "abs" or "if"

1.4k Views Asked by At

this is my code:

#include <stdio.h>
  void main() {
        char a, b;
        char c;
        printf("enter 2 chars: ");
        a = getchar();
        b = getchar();
        c = a - b;
        printf("%d",c );
  }

I'm trying to find the absolute value between two chars, for example, 'A'&'a'=>32 'a'&'A'=>32 my code shows negative answer,what should I do without using abs function or if, I tried this:

printf("%u",c );

but it gives me 4294967264. is there any simple way to do it? it should use getchar and putchar!

2

There are 2 best solutions below

3
On BEST ANSWER

Without branching: (assumes two's complement integer representation)

#include <stdio.h>

int main(void)
{
    printf("Enter 2 chars: ");
    char a = getchar();
    char b = getchar();
    char c = a - b;

    c = (c^-(c < 0)) + (c < 0);

    printf("%d\n", c);
}

Split in pieces:

(c < 0) gives 0 when c is positive:
c = (c^-0) + 0 ~> c = c^0 ... $foo XOR 0 gives $foo
c = c nothing to do.

(c < 0) gives 1 when c is negative:
c = (c^-1) + 1 ... -1 in two's complement is all bits set (~0)
c = (c^(~0)) + 1 ... a negative c in two's complement XOR ~0 gives -c - 1
c = -c - 1 + 1 ~> c = -c

gcc 8.3 -O3: (cl v15.9.0-pre.3.0 produces equivalent assembly)

mov     edx, edi    ; edx = c
shr     edx, 31     ; right shift, keep only the sign bit (c < 0) [sign]
mov     eax, edx    ; eax =  [sign]
neg     eax         ; eax = -[sign]
xor     eax, edi    ; eax = -[sign] xor c
add     eax, edx    ; eax += [sign]
15
On

The simplest way is to use the abs function.

printf("%d",abs(c) );

But if you do not want to use it, you can try change the line:

c = a - b;

to:

c = (a > b) ? (a-b) : (b - a);