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) )

 

3
1