BBC BASIC for Windows
« Rounding numbers »

Welcome Guest. Please Login or Register.
Apr 5th, 2018, 10:56pm



ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018.
Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.

If you require a dump of the post on your message board, please come to the support board and request it.


Thank you Conforums members.

BBC BASIC for Windows Resources
Online BBC BASIC for Windows documentation
BBC BASIC for Windows Beginners' Tutorial
BBC BASIC Home Page
BBC BASIC on Rosetta Code
BBC BASIC discussion group
BBC BASIC for Windows Programmers' Reference

« Previous Topic | Next Topic »
Pages: 1 2  Notify Send Topic Print
 hotthread  Author  Topic: Rounding numbers  (Read 2261 times)
CharlesB
New Member
Image


member is offline

Avatar




PM

Gender: Male
Posts: 46
xx Rounding numbers
« Thread started on: Apr 9th, 2015, 04:55am »

I'm sure that this is an elementary question, and surely, I have searched the help files many times for this simple answer, but I can't find it.

I simply want to round off a number to two decimal places.
I am aware of the PRINT FNUSING function and use it, but I am looking for something like USING$( ) that will actually convert (round off) a number.

So, may someone assist me to say, convert 34.8456123 to 34.85

Thank you, and please point me to the help files where I can learn to do this.
Charles
User IP Logged

Edja
Developer

member is offline

Avatar




PM


Posts: 60
xx Re: Rounding numbers
« Reply #1 on: Apr 9th, 2015, 07:04am »

Quote:
So, may someone assist me to say, convert 34.8456123 to 34.85
In Basic I would do something like this Code:
      a=34.8456123
      b=FNRound_2dec(a)
      PRINT b
      END

      DEFFNRound_2dec(a)=INT((a*100)+.5)/100 
But there are maybe more elegant solutions

If you would want to round to another number of decimals, say 3, you should multiply and divide by 1000

Eddy
User IP Logged

DDRM
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 321
xx Re: Rounding numbers
« Reply #2 on: Apr 9th, 2015, 08:49am »

Looks pretty concise to me! :-)

If it's useful, here's a more general function to round to a specified number of decimal places:

Code:
      a=34.8456023
      FOR ndp%=0 TO 6
        PRINT FNRound(a,ndp%)
      NEXT ndp%
      END

      DEFFNRound(n,places%)=INT(a*10^places%+.5)/10^places%
 


Note that:

a) Trailing 0s will be suppressed
b) It will actually work with negative numbers of "decimal places" - so if you specify -1 decimal places, it will round to the nearest 10!

Best wishes,

D
User IP Logged

rtr2
Guest
xx Re: Rounding numbers
« Reply #3 on: Apr 9th, 2015, 09:07am »

on Apr 9th, 2015, 04:55am, CharlesB wrote:
I simply want to round off a number to two decimal places. I am aware of the PRINT FNUSING function and use it, but I am looking for something like USING$( ) that will actually convert (round off) a number.

The functions listed by Edja and DDRM are fine, but it is probably worth adding a reminder that BBC BASIC works internally in binary floating-point so a value like 34.85 cannot be represented precisely. The actual value produced by their code, when run in BB4W v6.00a, is:

Code:
34.849999999999999998612221219218554324470460414886474609375 

So you perhaps should be asking yourself why you want to round the numbers, and whether it matters that the resulting value is not actually what you might like it to be.

Richard.
User IP Logged

DDRM
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 321
xx Re: Rounding numbers
« Reply #4 on: Apr 9th, 2015, 10:59am »

on Apr 9th, 2015, 09:07am, g4bau wrote:
The actual value produced by their code, when run in BB4W v6.00a, is:

Code:
34.849999999999999998612221219218554324470460414886474609375 




True, Oh Wise One, though I note that even in the "list variables" window it is given as 34.85, and that testing it against 34.85 does not report it as "less than", and does report it as "equals" - I guess that's obvious because 34.85 will map to the same (close!) binary approximation!

On occasion in the past when I've had issues related to this I've used something like

Code:
IF ABS(b-34.85)<1E-12 THEN PRINT "Good enough for me!" 
 


I guess with our new 64 bit integers we can use at least 1E-17! :-)

Best wishes,

D
User IP Logged

rtr2
Guest
xx Re: Rounding numbers
« Reply #5 on: Apr 9th, 2015, 1:59pm »

on Apr 9th, 2015, 10:59am, DDRM wrote:
testing it against 34.85 does not report it as "less than", and does report it as "equals"

It depends on how you do the test:

Code:
      IF 34.85 * 100 < 3485 THEN PRINT "Less than 34.85" 

Or indeed:

Code:
      PRINT 34.85 * 100 - 3485 

So the non-equality is very easy to demonstrate.

Quote:
I guess with our new 64 bit integers we can use at least 1E-17!

I assume you mean 80-bit floats, but either way it's not reliable. Indeed there's no tolerance that can be used with any confidence unless you know how many computational steps the value has passed through, each one of which is likely to have added a small error.

But there's a more fundamental point here: why does the OP want to round the value to two decimal places in the first place? The only point at which doing that is properly 'meaningful' is in a conversion from binary to a decimal string (for example in PRINT or STR$), and then the obvious method to use is FNusing(). But the OP says he is familiar with that usage and it doesn't do what he wants here.

In any other circumstance it's hard to see how 'rounding to (approximately) two decimal places' could be useful. One worry would be that the OP is actually trying to carry out financial calculations, when the rounding would be an attempt to give a result to the nearest penny or cent. But it is well known that financial calculations must not be carried out this way because errors can accumulate sufficiently to 'unbalance the books'. Instead one must perform only integer calculations (typically in units of pence or cents, but occasionally in smaller units), integer arithmetic being the only kind that is precisely accurate.

So this isn't some trivial detail that can be ignored in practice. I would want to know exactly why the OP thinks he wants to perform this rounding before being convinced it's not the result of a misunderstanding.

Richard.
« Last Edit: Apr 9th, 2015, 2:04pm by rtr2 » User IP Logged

CharlesB
New Member
Image


member is offline

Avatar




PM

Gender: Male
Posts: 46
xx Re: Rounding numbers
« Reply #6 on: Apr 9th, 2015, 4:44pm »

I want to thank you all so much for your knowledge and willingness to help. Richard, you hit the nail on the head. I do simply want to convert round off numbers for pricing. But, I'm not writing an accounting program so I don't think that I need to be concerned with minute errors in the variable value.

My purpose is for quotations. I want to be able to quote an item to a buyer in a table. I want the produce to break down to prices due to quantity purchased.

The buyer wants a certain quantity of a certain item. The item is priced by its weight/ft and its diameter. The item price is determined by running its weight/ft and diameter through a polynomial regression. Then a second formula calculates a quantity discount. The quotation should just be in Dollars and Cents.

I would want the buyer to see the price for his item as, for example $23.34/ft. rather than $23.3456789/ft. But, I also print the rounded number to a file and use it in a few other places where the PRINT FNUSING function does not work for me.



So, these numbers will never be additive, as in an accounting program. They serve one purpose, and this is for quotations. If the buyer responds and purchases, then we use QuickBooks for accounting.

I also want to print these numbers, rounded off to a file, and I tried the PRINT FNUSING("$##.##",item#) function, but had no success.

Again, I'm new to this.

Of the above answers to my query, which one would you recommend? Or, should I convert the variable (price#) to STR(price#) and then search for the decimal through INSTR, then etc ? I think that I should be able to handle this.

Again, this is not additive. Minor errors are not added in this program.

So, again, what do you think is the proper solution for a beginner to take?


User IP Logged

rtr2
Guest
xx Re: Rounding numbers
« Reply #7 on: Apr 9th, 2015, 5:11pm »

on Apr 9th, 2015, 4:44pm, CharlesB wrote:
I also want to print these numbers, rounded off to a file, and I tried the PRINT FNUSING("$##.##",item#) function, but had no success.

This works for me:

Code:
      INSTALL @lib$+"FNUSING"

      item = 34.8456123
      file% = OPENOUT(@usr$+"test.txt")
      PRINT #file%, FNusing("$##.##", item)
      BPUT #file%,10
      CLOSE #file% 

Does that not do what you want?

Richard.
User IP Logged

CharlesB
New Member
Image


member is offline

Avatar




PM

Gender: Male
Posts: 46
xx Re: Rounding numbers
« Reply #8 on: Apr 9th, 2015, 7:22pm »

Oh! This is so much better than what I was doing.
Below is what I was doing.

And, I was not separating the "PRINT" from the "FNusing" with the #5 . . . did not know that I could do this.

I do appreciate that you have provided a well-documented help file for learning file-writing in BBC BASIC, but I do find it one of the most challenging parts of my new endeavor.

not pretty, below. I have already modified this, but this is what I WAS doing.


Code:
    f& = OPENOUT("busadafiles\fabcard.dat") : IF f&=0 ERROR 53, "Cannot create file"
        SWAP @hfile%(f&), @hfile%(5)
  
        OSCLI "OUTPUT 5" : PRINT b$ : OSCLI "OUTPUT 0"
        OSCLI "OUTPUT 5" : PRINT c$ : OSCLI "OUTPUT 0"
        OSCLI "OUTPUT 5" : PRINT "Inner Diameter is "; BendsID$  : OSCLI "OUTPUT 0"
        OSCLI "OUTPUT 5" : PRINT "Outer Diameter is "; OD  : OSCLI "OUTPUT 0"
        OSCLI "OUTPUT 5" : PRINT "Bends Radius is ";Degree; " degrees"   : OSCLI "OUTPUT 0"
        OSCLI "OUTPUT 5" : PRINT "Left tangent  ";LT"  ";"Right tangent is ";RT : OSCLI "OUTPUT 0"
  
        OSCLI "OUTPUT 5" : PRINT "Left Tangent "; STR$(LT); " and the Right Tangent is "; RT : OSCLI "OUTPUT 0"
        OSCLI "OUTPUT 5" : PRINT "Arc is "; arcnumber$ : OSCLI "OUTPUT 0"
        OSCLI "OUTPUT 5" : PRINT "CUT  TUBE THIS LENGTH ------>"; STR$(centerlineLength) " "  : OSCLI "OUTPUT 0"
        OSCLI "OUTPUT 5" : PRINT "Circumference is "; CIRCUMFERENCE$ : OSCLI "OUTPUT 0"
        OSCLI "OUTPUT 5" : PRINT "Compass Bottom Arc At "; STR$(R - (OD / 2)); "  inches" : OSCLI "OUTPUT 0"
        OSCLI "OUTPUT 5" : PRINT "COMPASS CENTER LINE ARC At "; STR$(R) " inches" : OSCLI "OUTPUT 0"
        OSCLI "OUTPUT 5" : PRINT "COMPASS TOP ARC At "; STR$(R + (OD / 2)) " inches" : OSCLI "OUTPUT 0"
  
  
        CLOSE #5
 



The only problem that I am having now is that I can't seem to get the PRINT FNusing function to allow me to write its value on the same line with a descriptive string.

For example, I want a file line to read . . .

Your circumference should be 34.56 in.

But every modification of this line (except a colon) just gives me a syntax error, and the colon does not help me keep a single line. I was hoping that a semicolon would work, but I get a syntax error.
Code:
      PRINT #5, "Your circumference should be "
      PRINT #5, FNusing("##.###", circumference)
 


« Last Edit: Apr 9th, 2015, 8:13pm by CharlesB » User IP Logged

rtr2
Guest
xx Re: Rounding numbers
« Reply #9 on: Apr 9th, 2015, 9:21pm »

on Apr 9th, 2015, 7:22pm, CharlesB wrote:
Below is what I was doing.

That looks like code created by (or adapted from) the QB2BBC translator. As it says in the QB2BBC help: "the translated code can sometimes be difficult to read, and isn't necessarily much like what an experienced BBC BASIC programmer would write". If you're writing code yourself, it's not generally desirable to copy the kind of ugly code the translator produces!

Quote:
I can't seem to get the PRINT FNusing function to allow me to write its value on the same line with a descriptive string.

String concatenation (using the + operator) is a fundamental feature of virtually all BASIC dialects:

Code:
      PRINT #file%, "Your circumference should be " + \
      \             FNusing("##.###", circumference) 

Richard.
User IP Logged

CharlesB
New Member
Image


member is offline

Avatar




PM

Gender: Male
Posts: 46
xx Re: Rounding numbers
« Reply #10 on: Apr 10th, 2015, 03:18am »

Thank you Richard, you are right and I do remember reading that exact line in the qb translator. Yet, I am using the translator as a sort of tutorial . . . as I mentioned, I'm finding that file-handling is a bit difficult for me.

I am also slowly learning from, and using your provided example programs for files.

Thank you for your kind assistance.
User IP Logged

CharlesB
New Member
Image


member is offline

Avatar




PM

Gender: Male
Posts: 46
xx Re: Rounding numbers
« Reply #11 on: Apr 10th, 2015, 9:32pm »

Richard, not to take advantage of your time and kindness, but the following situation is another reason why I wanted rounded numbers and could not figure how to use the PRINT FNusing function as a solution.

I could think of no other way to produce a string with the proper "Price" value.

The code below is obviously wrong, but it is just one example of my frustrations.

Code:
c$ = "    "+ str$(Quantity%)+" "+  chr$(126)+ " ft "+ SelectedTubing$  + fnusing($##.##,Price) + "/ft. 20 ft lengths" 


I was able to use the help of Eddy and D to produce a rounded value for "Price," convert it to a String variable, and thus be able to move on. At least the string would make sense.

Code:
c$ = "    "+ STR$(Quantity%)+" "+  CHR$(126)+ " ft "+ SelectedTubing$  + "$" +FixedPrice2$+ "/ft. 20 ft lengths" 


The only problem was that their functions could produce a number as 40.9, where I would want a 40.90. This was simple to fix with some string manipulations, but not easy for me. This will really humble you!

In such a situation did I have a better alternative with PRINT FNusing?
« Last Edit: Apr 10th, 2015, 9:34pm by CharlesB » User IP Logged

Richey
New Member
Image


member is offline

Avatar




PM

Gender: Male
Posts: 35
xx Re: Rounding numbers
« Reply #12 on: Apr 10th, 2015, 10:24pm »

on Apr 9th, 2015, 04:55am, CharlesB wrote:
I'm sure that this is an elementary question, and surely, I have searched the help files many times for this simple answer, but I can't find it.

I simply want to round off a number to two decimal places.
I am aware of the PRINT FNUSING function and use it, but I am looking for something like USING$( ) that will actually convert (round off) a number.

So, may someone assist me to say, convert 34.8456123 to 34.85

Thank you, and please point me to the help files where I can learn to do this.
Charles


As someone who is still pretty much a novice, I tried to see if there was another way of doing this by practising what I have learnt about string slicing using MID$.

Here is my inelegant and clumsy effort. Apologies in advance for any errors / dodgy approaches:

Code:
      
      INPUT "Floating Point number to be truncated ";test
      INPUT "Rounded to how many decimal places ";places

      count=0
      convert$=STR$(test)
      LenOfString=LEN(convert$)

      FOR I=1 TO LenOfString
        a$=MID$(convert$,I,1)
        count=count+1
        IF a$="." THEN EXIT FOR
        PRINT a$;
      NEXT I

      PROC_decimal
      END

      DEF PROC_decimal
      PRINT MID$(convert$,count,places+1)
      ENDPROC
 

User IP Logged

rtr2
Guest
xx Re: Rounding numbers
« Reply #13 on: Apr 10th, 2015, 10:29pm »

on Apr 10th, 2015, 9:32pm, CharlesB wrote:
I wanted rounded numbers and could not figure how to use the PRINT FNusing function as a solution.

You seem to have got in your mind the false notion that FNusing() must be used in conjunction with PRINT. I wonder if this stems from your background with QBASIC (and other similar BASICs) in which it is indeed true that, stupidly, PRINT USING is the only usage.

But in BBC BASIC (with the FNUSING library), and also in Liberty BASIC, USING (or FNusing) is a regular function which can be used anywhere in your program; it is not at all tied to PRINT. Indeed a good way of thinking about it is that FNusing() has the same basic functionality as STR$(): they both take a numeric value and convert it into a decimal string.

The difference between STR$() and FNusing() is simply in how the formatting of the decimal number is controlled. With STR$() it is controlled using the special @% variable, whereas with FNusing() it is controlled by passing a special formatting string as the first parameter. But fundamentally the two functions do the same thing:

Code:
      INSTALL @lib$+"FNUSING"

      a = 34.8456123

      REM STR$ method (formatting controlled by @%):
      @% = &102020A
      a$ = STR$(a)
      PRINT a$

      REM FNusing method (with a formatting string):
      a$ = FNusing("##.##", a)
      PRINT a$ 


Quote:
The code below is obviously wrong, but it is just one example of my frustrations.

You don't actually say what your "frustration" is. In your code you use both STR$() and FNusing(), which is absolutely fine, but it is worth bearing in mind that they are effectively doing the same thing, just with different ways of controlling the formatting.

Putting your code in the context of an entire program it seems to work perfectly well, so again I don't see where the "frustration" arises:

Code:
      INSTALL @lib$+"FNUSING"

      Quantity% = 3
      SelectedTubing$ = "3/4 inch "
      Price = 23.3456789

      c$ = "    " + STR$(Quantity%) + " " + CHR$(126) + " ft " + \
      \ SelectedTubing$ + FNusing("$##.##", Price) + "/ft. 20 ft lengths"
      PRINT c$ 

I certainly don't think the functions offered by Edja and DDRM have any place here at all. Their contributions were well-meaning but have sent you in the wrong direction.

Richard.
User IP Logged

CharlesB
New Member
Image


member is offline

Avatar




PM

Gender: Male
Posts: 46
xx Re: Rounding numbers
« Reply #14 on: Apr 10th, 2015, 11:55pm »

Thank you again Richard.
This is very helpful and I've learned a lot.
My "frustrations" were just in my own inability to look at your help files (well written indeed), but to make proper sense of them so that I could correctly use them without introducing errors . . . again and again."

At first, I did not even understand that the FNusing could "operate" outside the realm of "PRINT". I mean, this is where I am.

Now I have something that I understand to work with, so again, thank you!
« Last Edit: Apr 10th, 2015, 11:59pm by CharlesB » User IP Logged

Pages: 1 2  Notify Send Topic Print
« Previous Topic | Next Topic »

| |

This forum powered for FREE by Conforums ©
Terms of Service | Privacy Policy | Conforums Support | Parental Controls