Symptom
Customer is using the PowerBuilder Round function with a Double datatype argument, sometimes it rounds correctly and sometimes it does not.
Environment
PowerBuilder
Reproducing the Issue
Using the following sample code, the result is not consistent for the double values entered.
double d_num1,d_num2
decimal new_dnum1, new_dnum2
d_num1 = 2.135
d_num2 = 3.135
new_dnum1 = Round(d_num1,2)
new_dnum2 = Round(d_num2,2)
Messagebox("Double Datatype Results of Rounding", "2.135 rounded to two decimal places = " +string(new_dnum1) + "~n~r" + "3.135 rounded to two decimal places = " + string(new_dnum2) )
Cause
This is not a PowerBuilder bug, it is expected behavior. The PB Round function is returning a decimal. To assure that you are getting the correct rounded value, use an argument with a decimal datatype.
Double and Decimal datatypes have different internal formats to store numbers. A PB Double datatype is an approximate numeric datatype and is subject to rounding errors after arithmetic operations. A PB Decimal data type is an exact numeric datatype. Only exact numeric data types are guaranteed to be accurate to the least significant digit specified after arithmetic operations. A Decimal datatype is a fixed point number. It is designed for financial calculation and should be used when accuracy is required such as in financial fields. In this specific case, where you are using the PB Round function, you should always use a decimal datatype argument to assure an accurate rounded value returned from the function.
This same behavior can be seen in other programming languages. As an example, this same behavior can be seen when passing a Double to the Math.Round(Double, Int32) method in a C# or VB application.
Resolution
You should always pass a decimal datatype to the PB Round() function. If you need to round a double value, you can use the code below to cast it first to a string and then to a decimal.
double d_num1,d_num2
string s_num1, s_num2
decimal new_dnum1, new_dnum2, dec_num1, dec_num2
d_num1 = 2.135
d_num2 = 3.135
s_num1 = string(d_num1)
s_num2 = string(d_num2)
dec_num1 = Dec(s_num1)
dec_num2 = Dec(s_num2)
new_dnum1 = Round(dec_num1,2)
new_dnum2 = Round(dec_num2,2)
Messagebox("Double Cast to String and Then to Decimal Results of Rounding", "2.135 rounded to two
decimal places = " + string(new_dnum1) + "~n~r" + "3.135 rounded to two decimal places = " +
string(new_dnum2) )