How to write absolute value in c

I know the solution is ugly and technically incorrect but I don't understand why the code doesn't work.

#include <stdio.h> #include <stdlib.h> #include <math.h> int main (int argc, char *argv[]) { int u; scanf("%d", &u); printf("absValue = %u\n", u); return 0; } 

%u specifies an unsigned decimal character but when I input a negative value, it gives

absValue = 4294967293 

Alternatively, with the if command, how to convert the negative sign to positive?

#include <stdio.h> #include <stdlib.h> #include <math.h> int main (int argc, char *argv[]) { int n; scanf("%d", &n); if(n < 0) { printf("absValue = -%d\n", n); } else { printf("absValue = %d\n", n); } return 0; } 
5

5 Answers

The shortest solution in your first piece of code is to change the printf statement as follows:

 printf("absValue = %u\n", (unsigned)((u<0)?-u:u)); 

This will print the absolute value of u. The type conversion (unsigned) ensures that the data type is as expected by printf. The statement (u<0)?-u:u uses the conditional operator to select the value -u if the condition (u<0) is true and u if the condition is false (i.e. u>=0).

The problem in your code is that u is a signed integer which means its value is stored using the Two's complement representation in 4 bytes(*) and printf is not intelligent. When you tell printf to display an unsigned integer, then printf will take the 4 bytes holding u and interpret them as an unsigned integer. Since negative numbers in Two's complement are stored as large positive integers, that is the result you see.

(*) The use of Two's complement and the int size of 4 is machine-dependent, but common.

12

As an alternative, you can also use the standard C function abs() (or one of its related functions):

7.22.6.1 The abs, labs and llabs functions

Synopsis

 #include <stdlib.h> int abs(int j); long int labs(long int j); long long int llabs(long long int j); 

Description

The abs, labs, and llabs functions compute the absolute value of an integer j. If the result cannot be represented, the behavior is undefined.

Returns

The abs, labs, and llabs, functions return the absolute value.

Footnotes

The absolute value of the most negative number cannot be represented in two's complement.

Note the footnote "The absolute value of the most negative number cannot be represented in two's complement." and "If the result cannot be represented, the behavior is undefined." Strictly speaking, you'd likely need to use long long int and llabs() to avoid undefined behavior in converting INT_MIN to a positive value, assuming a 32-bit int value, and long is often 32-bits, even on 64-bit Windows.

However, since double values are likely implemented in IEEE format with 53 bits of precision, a 32-bit int value can be converted to double with no loss of precision, so you can use the fabs() function to get the absolute value of a 32-bit int value in one call:

7.12.7.2 The fabs functions

Synopsis

 #include <math.h> double fabs(double x); float fabsf(float x); long double fabsl(long double x); 

The fabs functions compute the absolute value of a floating-point number x.

So your code would be:

#include <stdio.h> #include <math.h> int main (int argc, char *argv[]) { int u; scanf("%d", &u); printf("absValue = %u\n", (unsigned) fabs((double) u)); return 0; } 

Note that in (unsigned) fabs((double) u), casting u to double is not strictly necessary, as the int value will be implicitly converted to a double because of the double fabs(double) function prototype from stdlib.h. But the cast back to unsigned is exremely necessary to pass the unsigned int value you want to pass to printf().

You could also do this:

#include <stdio.h> #include <math.h> int main (int argc, char *argv[]) { int u; scanf("%d", &u); unsigned int absValue = fabs(u); printf("absValue = %u\n", absValue); return 0; } 

That works because unsigned int absValue is explicitly an unsigned int.

Also, on modern CPUs, conversion between int and double is usually done by a single relatively fast instruction.

How to write absolute value in c?

The shortest solution :

#include <stdlib.h> printf("absValue = %d\n", abs(u)); // clear and concise - yet see below 

Both printf("%d\n", abs(u)); and printf("%u\n", (unsigned)((u<0)?-u:u)); suffer the same problem: undefined behavior (UB) when n == INT_MIN1. The signed negation of INT_MIN is the UB.

At least abs(u) is clear, unlike (unsigned)((u<0)?-u:u).


To print the absolute value of an int, code could negate negative values with:
(-1 - n) + 1u or
-(unsigned)n or
0u - n
... and end up with an unsigned.2

I'd go for the simplest when a full range |int| is sought.

printf("absValue = %u\n", n < 0 ? 0u - n : (unsigned) n); 

Using long, long long or double poses their own troubles and portability. None warranted here.


1 when int is 2's complement encoded - very common.

2 C specified UINT_MAX >= INT_MAX. In the very rare implementations today, INT_MAX == INT_MAX is possible and code needs to resort to a wider type when int is non 2's complement.

printf doesn't convert the strings, but rather expects them converted. I would generally prefer to use the standard abs function which is declared in stdlib.h. This uses strtol to convert an argument to a long then convert that to an int. Nota bene, that, for example, if your machine uses two's-complements, calling abs(INT_MIN) produces undefined behaviour and should be dealt with. (Edited: error detection now complies with non-POSIX systems; see comments.)

#include <stdio.h> /* perror, printf */ #include <stdlib.h> /* strtol, abs */ #include <limits.h> /* INT_MIN, INT_MAX */ #include <errno.h> /* errno, ERANGE */ int main(int argc, char *argv[]) { int u; long input; char *end; /* Require one argument. */ if(argc != 2) return printf("Usage <number>\n"), EXIT_SUCCESS; /* `input` is converted from `argv[1]`, if it's 0, check that it actually read 0; check to see garbage characters at the end; check to see if the `input` is a) less then `INT_MIN`; b) also if `-INT_MAX < 0`, check that it is not lower than this value, because that will lead to undefined `abs`; c) more then `INT_MAX` -> if so, set `ERRNO` and enter the if. */ if( ((input = strtol(argv[1], &end, 0)) == 0 && end == argv[1]) || (*end != '\0' && (errno = EILSEQ, 1)) || ((input < INT_MIN || (-INT_MAX < 0 && input < -INT_MAX) || input > INT_MAX) && (errno = ERANGE, 1)) ) return perror("Input"), EXIT_FAILURE; /* We are pretty sure this cast is safe, now: `int abs(int)`. */ u = abs((int)input); printf("absValue(%ld) = %d\n", input, u); return EXIT_SUCCESS; } 

Checking edge cases,

bin/abs 2147483647 absValue(2147483647) = 2147483647 bin/abs 2147483648 Input: Result too large bin/abs -2147483648 Input: Result too large bin/abs -2147483647 absValue(-2147483647) = 2147483647 bin/abs Usage <number> bin/abs 0x10 absValue(16) = 16 bin/abs asdf Input: Invalid argument bin/abs 1a Input: Illegal byte sequence 
3

this is a function to get the absolute value of a number without using abs() function.

int abs_value(int *a){ return *a < 0 ? -*a: *a; } 

If you want to get the absolute difference between two numbers, here's how:

int abs_diff (int *a, int*b) { return *a > *b ? *a - *b : *b - *a; } 
3

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like