Page 1 of 1
How to Round to Decimals Places?
Posted: Fri Nov 12, 2010 5:49 pm
by swhite
Hi
In PB it appears that the Round() only rounds to Integers. So is the PB way to round to say 2 decimals places the following?
Code: Select all
lnCost.f = Round(10.4567*100,#PB_Round_Up)/100 ; answer should be 10.46
Thanks,
Simon
Re: How to Round to Decimals Places?
Posted: Fri Nov 12, 2010 5:55 pm
by Rook Zimbabwe
Code: Select all
incost.f = 10.426598745
Rstr$ = StrF(incost.f,2)
MessageRequester("VALUE", ""+Rstr$)
newflot.f = valf(Rstr$)
messagerequester("OUT", "Float reports: "+strf(newflot.f))
Keep in mind that ValF() always insists on 4 Decimals but as you can ssee that last fe are 0
And in a POS system or accounting system or a spreadsheet those won't matter...
Otherwise just write in the StrF(##,2) value!
Re: How to Round to Decimals Places?
Posted: Wed Nov 17, 2010 12:59 am
by nigel
Although I am relatively new to PureBasic, I immediately discovered the limitations of
PureBasic error detection, rounding and formatting in connection with monetary values.
I certainly needed a way to format and handle user entered monetary strings properly.
You may find the following subroutine which I developed to be useful in this regard :-
Code: Select all
;==========================================================
;SUBROUTINE TO CONVERT X$ TO MONEY STRING FORMAT USING TWO
;DECIMAL PLACES
;This subroutine ensures that the string does not contain
;any invalid characters outside the following :-
;0-9, ".", "-". Note that the minus sign is only permitted
;in the first character position. The decimal point must
;be expressed as a period character "." although it is
;easy to modify this subroutine and substitute the use of
;a comma instead of a period in countries where this need
;arises.
;
;Supplied - X$ Normally this would be a user entered value
;
;Returned - X$ Validated and rounded to two decimal places
; Invalid data will be indicated when X$
; contains the text "ERROR" instead of a
; formatted numeric string value.
;=========================================================
MONEYSTRING:
;Check if user entered zero in any form (which is OK)
If X$="0.00" Or X$="0.0" Or X$="0" Or Len(X$) < 1
X$="0.00"
Return
EndIf
;Make sure the string value is not any form of negative zero
If Left(X$,1)="-" And ValD(X$)=0
X$="ERROR"
Return
EndIf
;When first character is "." add a leading "0" to the string
If Left(X$,1)="."
X$="0"+X$
EndIf
;Make sure the string value is not "-."
If X$="-."
X$="ERROR"
Return
EndIf
;If string has length >2 and starts with "-.",
;make it start with "-0." instead
L=Len(X$)
If L > 2
If Left(X$,2)="-."
JCSPART1$=Left(X$,2)
JCSPART2$=Right(X$,(L-2))
X$="-0."+JCSPART2$
EndIf
Endif
;Check string only contains acceptable characters
;and not more than one "-" or "."
;Return ERROR if any invalid characters are found
;First pass through the string
L=Len(X$)
JCSXPERIOD=0
For JCSI = 1 to L
Result$=Mid(X$,JCSI,1)
;If a Dash is located, only allow it to appear in first character position
If Result$="-" And JCSI > 1
X$="ERROR"
Return
EndIf
;Only allow valid characters 0-9 and "."
If Result$ = "." Or Result$ = "-" Or (Result$ >="0" And Result$ <="9")
X$=X$
Else
X$="ERROR"
Return
Endif
;Count the number of periods entered.
;Return ERROR If more than one are found
If Result$="."
JCSXPERIOD=JCSXPERIOD+1
EndIf
If JCSXPERIOD >1
X$="ERROR"
Return
EndIf
Next JCSI
;Fix what comes after the decimal point if needed
;Also fix where there is no decimal point present
;Where string has no decimal point, then add ".00" to the end
If FindString(X$,".",1) = 0
X$=X$+".00"
Return
EndIf
;If string ends with a decimal point, add "00" to the end
If Right(X$,1)="."
X$=X$+"00"
Return
EndIf
;If string has one numeric after the decimal, add "0" to the end
L = Len(X$)
If Mid(X$,(L-1),1)="."
X$=X$+"0"
Return
EndIf
;Ignore cases where the decimal point is positioned correctly
L = Len(X$)
If Mid(X$,(L-2),1)="."
Return
EndIf
;Fix cases where more than two digits appear after the decimal point
;First, find position of the decimal point within the string
;If there are more than two chrs after decimal point, then eliminate
;the excess after rounding up or down for the 3rd digit taking account
;of handling both negative and positive values
XLength = FindString(X$,".",1)
;Perform rounding if needed
If Len(X$) > XLength+2
If ValD(X$) > 0
X.d=ValD(X$)+0.005
ElseIf ValD(X$) < 0
X.d=ValD(X$)-0.005
EndIf
X$=StrD(X.d)
XLength = FindString(X$,".",1)
EndIf
If Len(X$) > XLength+2
X$=Left(X$,XLength+2)
Return
EndIf
;Everything else is wrong
X$="ERROR"
RETURN
Re: How to Round to Decimals Places?
Posted: Wed Nov 17, 2010 8:54 am
by blueznl
When dealing with money it's best to decide up-front how many decimals you want to support. Following that build all your numbers in integer (.l or .i) and divide by 10^n for your number of digits, ie. $5.00 would then be stored as 500, and just before displaying or exporting one divides by 100.
Re: How to Round to Decimals Places?
Posted: Wed Nov 17, 2010 1:46 pm
by PB
+1 to what blueznl said. It's how most commerce apps work that I've seen,
and I've worked in debt collection and currently in a job that deals with LOTS
of public money. All the apps I've used NEVER have a decimal point for cents.
To specify $49.95, I would enter 4995, and so on. Blueznl is absolutely right,
and it lets you avoid using lots of workaround code like Nigel posted.
Re: How to Round to Decimals Places?
Posted: Wed Nov 17, 2010 8:36 pm
by blueznl
I've been involved with some (telecom) billing systems ages ago, which dealt with different valuta. One of the problems we ran into was the lack of accuracy, one of the platforms was 4 digits, ie. $0.0001 accuracy, which was internally stored as 1. In the beginning we thought it was accurate enough (mimicking accuracy of certain valuta traders), until we realized billing was done per second, whilst pricing was entered in minutes, ie. we needed at least 60 times the accuracy

Caused quite a few problems as we had some valuata in 'millions' whilst others in 'cents'. It was all solved nicely in the end, but caused some headaches at the time

Re: How to Round to Decimals Places?
Posted: Thu Nov 18, 2010 1:15 pm
by nigel
I have worked within business IT systems in the Corporate world for many decades, designing and implementing "Non-Windows" based ERP systems. My employers have included organisations ranging in size from 300 - 40,000 employees and having annual revenues between tens of millions and billions of dollars. During most of these years I have worked on minicomputer and mainframe computer platforms from IBM, DEC and HP using a variety of programming languages including COBOL and BASIC. I have never encountered difficulties with precision regarding monetary values because the development tools are designed to handle this properly. In these environments, the programming languages provide support for "Decimal data types". HP Basic even supported the use of string arithmetic operations, providing precision levels between 56 to 60 significant digits should this be needed. Scaling declarations could also be used for floating point operations and error handling support was available at the individual statement line level without having to use line numbers and "ON ERROR GOTO" statements.
PureBasic was clearly not designed with the development of business software in mind. However, although I am new to this language I have found PureBasic to be a very good product and so far I have been able to circumvent many of these limitations relatively easily. PureBasic is an amazing product considering it has been developed on a shoestring budget by a handful of individuals. I do not regret for an instant choosing PureBasic and so far I would say that it can be used effectively for business applications. If Fred Laboureur had more time and money his PureBasic brainchild could easily turn into a powerhouse product.