Read Origin

技术博主

  • 多看开发者大会!
  1. ThePrimeTime
  2. CodeAesthetic
  3. Molly Rocket

What’s so special about 2147483648?

by Sandra Henry-Stocker, Unix Dweeb, from NetWorkWorld 945870
tags: Data Center, Linux, Open Source
难度:EASY

First of all, it’s a power of 2. That’s undoubtedly not the most obvious thing unless you’re some kind of mathematical genius. And, to be exact, it’s 2^31. That’s significant — as you’ll see in a minute.

In binary, 2147483647 is 01111111111111111111111111111111 and it’s the biggest positive number that will fit in 32 bits when using the “two’s complement” notation (补码) — the way of representing numbers that allows for negative values. If we could use that leftmost (high order) bit, the largest possible number would be twice as large since every extra bit doubles the range of numbers that a binary number can represent.

And 2147483648 just happens to be the number you’d get if you multiplied 256 * 256 * 256 * 256 and then divided the result by 2. Not excited yet? Give me a moment.

The 32nd bit that remains in our 4 byte or 32 bit number is used to represent whether the number is positive or negative. If it’s a 0, as in 0111 1111 1111 1111 1111 1111 1111 1111, the number is +2147483647 If it’s a 1, as in 1111 1111 1111 1111 1111 1111 1111 1111, the number is -2147483648 (错误,应该是-2147483647!).

负数的补码 = 正数各位取反 + 1
2147483647(011…111B) + 1 = 2147483648(100…000B), 则
-2147483648 = 011…111B + 1 = 100.000B

So, Unix systems have a way to express a wide range of numeric values and a way to represent negative numbers. This doesn’t mean that you can’t work with numbers that are much larger. On today’s Linux systems, 2147483648 is NOT even close to the largest numbers that you can manipulate. Just take a look at this little excerpt from my playing around on the command line on my AWS system:

$ echo $n
25227339711002779721296336059113506713437716431793799076536161744218926098
42688929348009219253857839258425602022609412708599928289785519021711589989
59576178192
$ n=`expr $n * 9999`
$ echo $n
25224816977031679443324206425507595362766372660150619696628508128044504205
81704660455074418331932453474499759462407151767329068296956540469809418830
596802205741808

Obviously, the numbers that you can work with on the command line can take on a much larger range of values. Even so, 2147483647 has a certain claim to fame. This number represents the latest (i.e., furthest into the future) date that can be represented on Unix systems — at least for now. Sometime before 2038, the developers of various “flavors” of Unix will have to figure out what to do next. Why is this important and why 2038?

To understand why this is so important, you have to consider how Unix stores dates. To see the current date and time expressed in binary, use the date command like this:

date +%s
1449012345

You’ve probably heard references to the Unix “epoch”. Meant to imply, more or less, the birth of Unix, the epoch refers to Jan 1, 1970. If you had created a file at the start of that day, the date associated with it would be stored in the system as 0. If we use the date command’s -d option, we can get it to translate the date “0” to a date/time string like this:

$ date -d @0
Thu Jan 1 00:00:00 UTC 1970

And if we, instead, use the maximum value for dates, we would get this:

$ date -d @2147483647
Tue Jan 19 03:14:07 UTC 2038

Conversely, the minimum date jumps back from the epoch (Jan 1, 1970) the same number of seconds as the maximum date jumps forward:

$ date -d@-2147483648
Fri Dec 13 20:45:52 UTC 1901

This means that the largest date that can be stored on a Unix system is Jan 19, 2038 and, much like the Y2K that worried people sixteen years ago, the 2038 problem threatens to disrupt systems and devices when the date rolls over from 01111111111111111111111111111111 to 10000000000000000000000000000000 and are likely interpreted as December 13, 1901. By that time, the powers that be might add another byte or two to date/time representations or might stop using the two’s complement format, giving us another 68 years or so to worry about the problem. And hopefully we won’t have too many systems driving the planet or rotating around it that can’t be adjusted to the new dates.

The Y2K issue was really only a problem because numerous applications stored years as 2 digit fields so, once the year 2000 began, it would look to them like 1900. And yet, in spite of all the sturm and drang, we moved into the 21st century with a lot fewer problems that many of us were anticipating.

The 2038 problem will take a lot more time and attention because it involves the internal representation of dates with second by second precision. And those dates and times are critical to a lot of processes and a lot of equipment. But it’s only 1449012345. We still have time.