Library function | big event! std::abs() failed

Caption: when brushing LeetCode on 10 / 4 / 2021, it was blocked by a strange case and failed to AC

Involved: [original code / complement] [C library function abs]

After the following code is executed, the result is?

#include <cstdlib>
#include <iostream>
using namespace std;

int main()
{
    int val = (1 << (sizeof(int)*8 - 1) );	// -2147483648 = -2^31
    val = abs(val);
    cout << val << endl;
}

Correct answer: - 2147483648 (val has not changed after abs() processing)

(⊙ˍ⊙)?WHY?WHY?

Fog tracking

The library function std::abs() is an absolute value function that returns the absolute value of the passed in parameter!

But obviously, in the above code, the ability of taking absolute value of std::abs() has failed, so it is urgent to find out the implementation of std::abs().

(because std::abs() is a library function, and the library function is a standard for function implementation formulated by C Standards Association. The specific implementation contents may be inconsistent on various platforms. Here I am looking for the implementation version under Linux platform)

#include <stdlib.h>

#undef	abs

/* Return the absolute value of I.  */
int
abs (int i)
{
  return i < 0 ? -i : i;
}

return i < 0 ? -i : i

??? (⊙x⊙;) ???
-(- 2147483648) is not equal to 2147483648? Can we say that the operation of logarithm taking negative value in C language is not as I think?

List what you know first:

  1. Variable size of int type 4 byte s
  2. Integer variables such as int use "complement" to represent negative numbers
  3. Data range that int can represent: [- 2 ^ 31, - 1] & [0, 2 ^ 31-1]
int val = 1;
val = -val;		// What is the process like?

In the relevant books on computer composition, it is said that "negative numbers are represented by complement, complement = inverse of original code + 1".

Here we take the above theory directly to see what results will be obtained.

int val =  1;	0000:0001
    val = -val;	1111:1111 [Correct result]
/*
1. Reverse 0000:0001 - > 1111:1110
2. Add one 1111:1110 - > 1111:1111 (coincidence)
*/

Here we only tested "positive - > negative", and now we will test "negative - > positive"

int val = -1;	1111:1111
    val = -val; 0000:0001 [Correct result]
/*
1. Minus one 1111:1111 - > 1111:1110
2. Reverse 1111:1110 - > 0000:0001 (coincidence)
*/

Now bring 2147483648 into the calculation process we just mastered:

-2147483648 == 10-00-00-00
1. Minus 10-00-00-00 -> 7f-ff-ff-ff
2. Reverse 7 f-ff-ff-ff -> 10-00-00-00

_(:з)∠)_ AWSL. . . 

According to the negative processing method in C, - 2147483648 will indeed be equal to itself.

Emmmm, but why is this happening? It seems that this problem returns to the principle of computer composition.
At that time, I didn't learn coding very thoroughly. It seems that I have to make up a missed lesson this time

(the following is the analysis process)

int type size = 4 byte = 4 * 8 = 32 bit = 2^32 expressible data
The data range is a little larger than 100 million. I'll narrow it down:
int type size = 0.5 byte = 4 bit = 16 kinds of expressible data

1111 [-1]----
1110 [-2]    |
1101 [-3]    |
1100 [-4]    |
1011 [-5]    |
1010 [-6]    |
1001 [-7]    |
1000 [-8]    |
=========    |
0111 [7]     |
0110 [6]     |
0101 [5]     |
0100 [4]     |
0011 [3]     |
0010 [2]     |
0001 [1]     |
0000 [0]-----

Negative - > positive: - 1. Negative

Positive - > negative: negative, + 1

In fact, what should be confused here is:

  1. Why should I "take the opposite"
  2. Why do I want "+ 1"“

Now please look at the code box above with these questions and carefully analyze the rules inside.

It is not difficult to find: "the negative number represented by the complement is just one grid away from the positive number, so it can be axisymmetric"!!!
At this time, looking back at the positive and negative conversion mechanism provided by C language, we can find that "+ 1 / - 1" is just to make the positive and negative fill the gap to achieve the goal of axisymmetry.

eg:

1 to -1
1>  1 Reverse, get -2 [0001 -> 1110]
2> -2 Plus one, yes -1 [1110 -> 1111]

Summary:

Fog tracking abstracts two questions as road signs:

  1. Why does the std::abs() library function fail when val = -2147483648
  2. Why does the "take negative" operation provided by C language make - 2147483648 equal to ta self

Question ① remuneration after problem solving:

  1. "Obtained the concrete implementation of std::abs() provided by Linux"
  2. "How is the negative value operation of C performed?"

② remuneration after problem solving:

  1. "Thoroughly understand how the complement original code conversion formula in computer composition is derived"

Tags: C++ Linux glibc

Posted on Tue, 05 Oct 2021 20:27:39 -0400 by tomjung09