How to Round to Decimals Places?

Just starting out? Need help? Post your questions and find answers here.
swhite
Enthusiast
Enthusiast
Posts: 789
Joined: Thu May 21, 2009 6:56 pm

How to Round to Decimals Places?

Post 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
Simon White
dCipher Computing
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Re: How to Round to Decimals Places?

Post 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!
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
nigel
User
User
Posts: 62
Joined: Tue Feb 23, 2010 8:39 pm
Location: Canada

Re: How to Round to Decimals Places?

Post 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
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: How to Round to Decimals Places?

Post 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.
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: How to Round to Decimals Places?

Post 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.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: How to Round to Decimals Places?

Post 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 :-)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
nigel
User
User
Posts: 62
Joined: Tue Feb 23, 2010 8:39 pm
Location: Canada

Re: How to Round to Decimals Places?

Post 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.
Post Reply