1. Rounding method Rounding is a very widely used approximate calculation method, which includes two types: arithmetic rounding method and banker rounding method. The so-called arithmetic rounding method is the rounding method in our usual sense. The rule is: when the value of the abandoned bit is greater than or equal to 5, the bit is withdrawn while the bit is withdrawn; when the value of the abandoned bit is less than 5, the bit is withdrawn directly. The so-called banker rounding method is essentially a method of rounding four rounding six into five and keeping double (also known as rounding six into five odd and even). The rules are: when the value of the abandoned bit is less than 5, the bit is abandoned directly; when the value of the abandoned bit is greater than or equal to 6, the bit is returned to the front while the bit is abandoned; when the value of the left bit is abandoned When equal to 5, if the value of the previous digit is odd, then the bit is dropped while the bit is dropped. If the value of the previous digit is even, then the bit is dropped directly. To sum up, the results obtained by the two rounding methods are not consistent, so they must be distinguished according to actual needs when using them. Otherwise, some inexplicable deviations will occur. 2. The rounding function in Delphi is well known. There is a rounding rounding function in Delphi. However, it implements rounding operations according to the rules of the banker rounding method. There is no rounding rounding function in Delphi that implements rounding operations according to the rules of the arithmetic rounding method. Using rounding function in Delphi has always been using Round, but sometimes I found that the answers obtained by using it will be different from what we expected. For example: i := Round(11.5) Result: i=12i := Round(10.5) Result: i=10 Yes, according to our expectations, the second function should return 11, but why is this happening? For XXX.5, the integer part is an odd number, then Round Up will be Round Down. Is it a Delphi bug? No!! Let's see a sentence on <<Pascal>>: In recent versions of the Delphi Pascal compiler, the Round function is based on the CPU's FPU (floating point component) processor. Basic. This processor uses the so-called banker rounding method, that is, when implementing the Round function on the intermediate value (such as 5.5, 6.5), the processor determines whether the rounding is based on the odd and even nature of the number before the decimal point, such as 5.5 Round The result is 6, and the result of 6.5 Round is also 6, because 6 is an even number. The Round function actually uses the banker algorithm for operations, and it is generally statistically used to use this algorithm, which is more scientific than our traditional rounding method. However, if we want to use the traditional rounding method, how can we solve it? Someone solved this way, adding a very small value to 10.5, and then calling the Round function. This way, without affecting the accuracy, you get the correct result. It seems good, but this is always a way to treat the symptoms but not the root cause. There is no more orthodox solution? Another function was found on the Internet: function DoRound(Value: Extended): Int64; PRocedure Set8087CW(NewCW: Word); asm MOV Default8087CW,AX FNCLEX FLDCW Default8087CW end;const RoundUpCW = $1B32;var OldCW : Word; began OldCW : = Default8087CW; try Set8087CW(RoundUpCW); Result := Round(Value); finally Set8087CW(OldCW); end; end; first explain 8087CW, the full name is 8087 control word. It is the value of the floating point unit (FPU) controller control word in the CPU. Setting 8087CW will change the FPU accuracy, rounding mode, and whether an exception occurs when an operation error occurs. The idea of the above program is very simple, which is to save 8087CW first, then set it to Round Up, so that when even numbers are not Round Down, and finally restore 8087CW. In fact, the above function can be simplified. Because the implementation of Set8087CW has been provided in the System unit, the program is simplified to function DoRound(Value: Extended): Int64;const RoundUpCW = $1B32;var OldCW : Word; begin OldCW := Default8087CW; try Set8087CW(RoundUpCW); Result := Round(Value); finally Set8087CW(OldCW); end;end; Until here, this article can come to an end, but after exploration, I found another similar and interesting one Solution. In fact, Borland had long thought that we would encounter such a problem, and thought that we needed to customize the rounding mode of the FPU, so it provided ready-made functions for us to use. In the Math unit, there is a SetRoundMode function. Below is a rounding function I encapsulated: function RoundEx(Value: Extended; RoundMode: TFPURoundingMode = rmUp): Int64;var RM: TFPURoundingMode; begin RM := GetRoundMode; try SetRoundMode(RoundMode); Result := Round(Value); Finally SetRoundMode(RM); end;end;Example: i := RoundEx(11.5) Result: i=12i := RoundEx(10.5) Result: i=11 Well, that's right, what will happen if I set it to other RoundModes Woolen cloth? For example: i := RoundEx(11.5, rmTruncate) Result: i=11i := RoundEx(10.5, rmTruncate) Result: i=10RoundEx function has been transformed into a Trunc function gorgeously. Isn't it very interesting? Haha!