Today, we will dive into the technical details and discuss the differences in floating-point computing between .NET and the .NET Framework.

Introduction

In .NET Core 3.0, changes were made to floating-point parsing and formatting to comply with the IEEE 754-2008 standard. You can read more about these changes in this article. When working with Stimulsoft products, these changes most commonly manifest in rounding numbers and the appearance of a "negatively signed" zero.

Negative zero

Negatively and positively signed zeros are used in mathematical analysis as conventional symbols for negative and positive infinitesimal quantities. In typical programming tasks, a regular zero suffices, but some advanced mathematical calculations require these distinctions. To address this, "negatively signed zero" was introduced.

Negative zero is the result of rounding negative numbers. For example, previously, the result of Math.Round(-0.01, 0) was "0", but now it is "-0". This also appears when formatting numbers (Number, Currency, Percent formats), as rounding is used in the formatting process. Mathematically, this approach is more accurate. However, from a programming perspective, it is considered a "breaking change", since the standard behavior of the rounding operation has changed, and there is no straightforward way to disable this modification.

To resolve the issue of negative zero appearing, we revised our .NET Core series products so that, by default, negatively signed zero is replaced with regular zero. However, if your calculations still require negative zero, you can enable it by setting the StiOptions.Engine.AllowNegativeZero = true option.

Rounding of numbers

One of the improvements in .NET Core 3.0 involves changes to the syntax analysis of floating-point numbers. The reason for this improvement lies in how numbers are stored in the float and double types. These numbers are stored in binary form and are only converted to decimal when rounding or displaying on the screen. For example, the number "0.0045" is actually stored in memory as something like "0.0044999999999999996". A special method then "restores" the original number from this binary representation when it is displayed. As a result, it is impossible to precisely represent decimal numbers in float and double types - they will always contain some level of error.

Previously, the algorithms for these number conversions с from those specified in the IEEE 754-2008 standard, which led to different calculation results on different systems. Now, with the updates in .NET Core 3.0, calculation results adhere to the standard. However, this can result in different outcomes compared to earlier versions, which also affects the standard Round function, potentially producing different results than before.

This has caused issues for some clients who maintain both .NET Framework and .NET Core versions of their products, as they are now seeing differing results across the two versions. Please note!

To ensure that calculation results are consistent and predictable across different environments, we recommend using the following approach: in all critical calculations, cast types to Decimal. This will guarantee accurate rounding and minimize errors in any calculations.
Modifying multiple reports is easy, but some users have encountered the need to rework many previously created reports. For such cases, we have added a new option:
StiOptions.Engine.ForceConversionToDecimalInTextFormat = false;
By default, this option is disabled. If you set it to true, then when formatting text in Number, Currency, and Percentage formats, float and double arguments will automatically be converted to Decimal to improve rounding accuracy.

The MidpointRounding parameter

To achieve bank rounding, you need to use the MidpointRounding.AwayFromZero parameter in the standard Math.Round function. For your convenience, we previously added this parameter to our custom Round function. Based on user requests, we also made it possible to set the default value of this parameter so that you do not have to update all report templates. To do this, you can configure the following option:
StiOptions.Engine.MidpointRounding = MidpointRounding.AwayFromZero;
By using the above options, you can manage calculation accuracy and avoid potential issues when migrating your product to .NET.
By using this website, you agree to the use of cookies for analytics and personalized content. Cookies store useful information on your computer to help us improve efficiency and usability. For more information, please read the privacy policy and cookie policy.