Why has the rounding behavior of double and single values changed in sprintf and fprintf?

33 visualizaciones (últimos 30 días)
Why has the rounding behavior of double and single values changed when printing them with functions like "sprintf" and "fprintf"?
Instead of rounding halves away from zero, it will sometimes round down toward zero. For example,
>> fprintf('%.0f\n',3.5) % Rounds up away from zero
4
>> fprintf('%.0f\n',2.5) % Rounds down toward zero
2

Respuesta aceptada

MathWorks Support Team
MathWorks Support Team el 10 de Sept. de 2021
Editada: MathWorks Support Team el 27 de Dic. de 2021
The rounding method used when printing floating-point numbers (double or single) changed from the "Common Method" to "Banker's (Nearest Even) Method" by Microsoft in Windows 10 update 2004, Build 19041 on May 28, 2020. It is intentional and brings Windows in line with all other supported architectures. You may have observed this change in MATLAB when printing floating-point numbers with the "fprintf" and "sprintf" functions.
This update has a related precision bug (discussed separately below). The bug was fixed in both 
  and 
How does the update affect you?
Any version of MATLAB that runs on Windows 10 update 2004 will see this new rounding behavior when printing floating-point numbers.
The update affects how ties are broken -- when the last digit of precision on the underlying representation is exactly a 5. The old behavior used the "Common method" of rounding, which broke the tie by rounding to the nearest value away from zero.
Old Behavior: 
>> vals = 1.5:4.5;
>> fprintf('%8.1f --> %.0f\n', [vals; vals])
1.5-->2
2.5-->3
3.5-->4
4.5-->5
The new behavior uses "Banker's method", which breaks the tie by rounding to the nearest even.
New Behavior:
>> vals = 1.5:4.5;
>> fprintf('%8.1f --> %.0f\n',[vals; vals])
1.5-->2
2.5-->2
3.5-->4
4.5-->4
Note: In some instances, you may find Banker's rounding not being used when you would expect it to. For example,
>> fprintf("%.1f\n",1.15)
1.1
You might expect the number 1.15 to be rounded to the nearest even, 1.2. However, this is not the case because of how floating-point numbers are represented in binary. If we increase the number of digits of precision, we see that 1.15 gets converted to a floating-point number slightly less than 1.15:
>> fprintf("%.17f\n",1.15)
1.14999999999999991
Since this is technically not a tie, the number rounds down to 1.1.
For more information, please refer to the
This change in behavior of the rounding mode is a permanent change. If you want to see more precision, use more digits in the precision part of the printing function’s format specifier. 
 
The change in rounding mode (in the Windows Update) also introduced a precision bug.
The bug is that “round to nearest even” is being employed even for values that are not exactly a 5 in the last digit.  For example,  
Before the update: 
>> sprintf("%.1f",1.251)
ans = 1.3
After the update: 
>> sprintf("%.1f",1.251)
ans = 1.2
While rounding 1.251 to 1 decimal place, it employs the tie breaker rule for 0.05 and ignores the digits beyond 5. Thus 1.251 is incorrectly rounded down to the nearest even, 1.2.  Since this value is not a “tie”, it should be rounded up to 1.3. 

Más respuestas (0)

Categorías

Más información sobre Creating and Concatenating Matrices en Help Center y File Exchange.

Etiquetas

Aún no se han introducido etiquetas.

Productos

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by