Author: jillzhang
Contact: jillzhang@126.com
This article is original and reposted. Please retain the source and author. Thank you.
In C and C # languages, float and double types are used to store data of the floating point type.
32bit, double data occupies 64bit. We declare a variable float F =
How is the memory allocated in 2.25f? If it is randomly allocated, isn't the world a mess? In fact, both float and double are subject to IEEE specifications in terms of storage methods.
Float follows IEEE r32.24, while double follows r64.53.
Both single precision and double precision are divided into three parts in storage:
- Sign (sign): 0 indicates positive, 1 indicates negative
- Exponent: used to store exponential data in scientific notation and stored in shift mode.
- Mantissa: mantissa
Shows the storage method of float:
The dual-precision storage method is:
Both r32.24 and r64.53 use scientific notation to store data. For example, 8.25 is represented as 8.25 * in decimal notation *
And 120.5 can be represented as: 1.205 *
,
I don't need to talk about these primary school knowledge. While our silly computer doesn't know the decimal data at all. He only knows the numbers 0, 1. Therefore, in computer storage, we must first change the above number to the binary scientific count.
8.25 can be expressed as 1000.01 in binary format. I rely on it and it won't even be converted, right? Then I guess it's okay. 120.5 in binary format: 1110110.1
The binary scientific notation can be expressed as 1000.01 *
, 1110110.1 can be expressed as 1.1101101 *
The scientific notation of any number is 1. xxx *
,
The ending part can be expressed as XXXX, and the first part is 1. Why do we need to express it? You can omit 1 before the decimal point, so the accuracy of the 23bit ending part is changed
The truth is here, the 24bit can be precise to the number of digits after the decimal point. We know that the binary value of 9 is 1001, so the 4bit can be accurate to one decimal place.
Point, 24bit enables float to be accurate to 6 digits after the decimal point, and for the index part, because the index can be positive and negative, the index range that the eight-digit index can represent should be: -127-128,
Therefore, the index storage adopts shift storage, and the stored data is metadata + 127. Let's take a look at the real storage methods of 8.25 and 120.5 in the memory.
First, let's take a look at 8.25, which is represented by the binary scientific Notation: 1.0001 *
According to the above storage method, the symbol bit is: 0, indicating positive, the index bit is: 3 + 127 = 130, and the number of digits is, so the storage method of 8.25 is shown in:
The Storage Method of Single-precision floating point number 120.5 is shown in:
How do you know the decimal value of a piece of data in the memory that is stored in a single precision? It is actually the reverse push process, for example, the following memory
Data: 0100001011101101000000000000. First, we split the data, 0 10000 0101 110 1101
0000 0000 0000, as shown in the memory storage:
According to our calculation method, we can calculate that such a set of data is expressed as: 1.1101101 *
= 120.5
The storage of double-precision floating-point numbers is similar to that of single-precision data. The difference is the number of digits in the index and tail. So I will not describe the double-precision storage method in detail here. I will only show the last storage mode diagram of 120.5. You can think about why this is the case.
Below I will solve one of our doubts with this basic knowledge point. Please refer to the following program and observe the output results.
Float F = 2.2f;
Double D = (double) F;
Console. writeline (D. tostring ("0.0000000000000 "));
F = 2.25f;
D = (double) F;
Console. writeline (D. tostring ("0.0000000000000 "));
The output may be confusing. After 2.2 of the single precision is converted to double precision, it is accurate to 13 decimal places and then changed to 2.2000000476837.
After 2.25 is converted to double precision, it is changed to 2.2500000000000. Why is the value 2.2 After conversion changed, but 2.25 is not changed? Strange, right? In fact
Storage results, we can find the answer. First, let's take a look at the 2.25 Single-precision storage method. It's very simple: 0 1000 0001 001 0000 0000
0000 0000 0000, and 2.25 dual-precision representation: 0 100 0000 0001 0010 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000
0000. In this way, the value of 2.25 will not change during forced conversion. Let's look at 2.2 again. 2.2 should be represented by scientific Notation: converts decimal places to decimal places.
So 0.282 = 0.4. Therefore, the first part of the binary decimal point is 0, 0.4 × 2 = 0.4, and the second digit is
0, 0.8*2 = 1.6, the third digit is 1, 0.6*2 =
1.2, the fourth digit is 1, 0.2*2 = 0.4, and the fifth digit is 0, which is never possible to multiply to = 1.0. The obtained binary is an infinite loop arrangement.
00110011001100110011... for Single-precision data, the ending number can only represent the precision of 24 bit, so 2.2 of Float storage is:
However, in this storage mode, the value converted to decimal is not 2.2. It may be inaccurate when the decimal is converted to binary, such as 2.2, while the double type.
The same problem also exists, so there will be some errors in the floating point representation. When the single precision is converted to double precision, there will also be errors, for decimal data that can be expressed in binary, such
2.25, this error will not exist, so the above strange output results will appear.
This article is original by the author and is only published in the blog Park. I hope you can indicate the source and author when you reprint it. Thank you.
Note: In the writing process, the following documents are referenced:
Http://www.msdn.net/library/chs/default.asp? Url =/library/CHS/vccore/html/_ core_why_floating_point_numbers_may_lose_precision.asp
Http://blog.csdn.net/ganxingming/archive/2006/12/19/1449526.aspx