The QBasic / QB64 Discussion Forum      Other Subforums, Links and Downloads
 
 


  << Previous Topic | Next Topic >>Return to Index  

Some advice for Gary

August 27 2007 at 5:27 AM
Laanan Fisher  (no login)

 
In response to this post:
http://www.network54.com/Forum/13959/message/1188146191/Updating+Primitive+files

const filename = "text.txt"

' This declares and defines a variable called 'earliestdate' of INTEGER type.
' INTEGER datatypes are numbers capable of storing whole numbers from -32768 to
' 32767. Variables that are not declared before they are used (assigned to,
' passed to procedures, PRINTed, etc.) are implicitly declared to be of SINGLE
' type, which can store rational numbers as well as whole numbers. In general,
' it's good to explicitly declare variables and their data types (with DIM)
' rather than just relying on implicit declaration, since it gives you some
' place in the code to look at in case you need to verify the datatype of a
' variable. (Some people use so-called 'type-suffixes' which are symbols
' appended to the end of a variable name that determines its type, but that can
' introduce hard to track down bugs if you forget-to-append-the-symbol/append-
' the-wrong-symbol. Personally I think it makes the code look messy)
dim earliestdate as integer

print "Earliest date to include: " ;
input earliestdate

' FREEFILE is a procedure in the QuickBASIC/QBasic runtime library that returns
' a valid file number (of INTEGER type) to use in other I/O procedures. This is
' also a good habit to get into since it provides a way to name the file
' numbers you use, rather than having a bunch of 'magic numbers' (numeric
' literals) floating around everywhere, that make changes to the code difficult.
dim filenum as integer : filenum = freefile
open filename for input as filenum

' Sums are grouped in 9 ranges stored in an array. An array is collection of
' one or more variables all of the same data type. These variable, or elements,
' are accessed via the '()' operator using an index, which is the position of
' the element in the array. Usually it is better to use an array rather than
' many separate variables when they each share a common kind of information to
' be stored - in this case, the total s for sums that fall in a range.
' index: 1 2 3 4 5 6 7 8 9
' sum range: [1-3][4-6][7-9][10-12][13-15][16-18][19-21][22-24][25+]
dim sums(1 to 9) as integer

' It's very important to create clear and helpful variable names too. The more
' descriptive your variable names are, the easier it will be to follow what the
' code is doing. Common sense should kick in about just how descriptive, but
' just remember that well written code will largely document itself and you
' will have less need for comments. BTW, it may help to use a different text
' editor than QB.EXE/QBASIC.EXE, one that supports syntax highlighting. I've
' pasted the code at copy-pasta.com so that all these rants will be colored
' for clarity - it really helps to have the colored text once you start working
' in it, not to mention you have your choice of Windows/Linux text editors so
' you're not stuck in the 25x80/50x80 text mode (I like lots of text on the
' screen and not having to scroll so often). I use Crimson Editor for most of
' my BASIC coding in Windows, gedit in Linux.
dim total as integer
dim sumcount as integer

' The low and high sums are separate variables because they provide a different
' kind of information than the elements in the array.
dim lowestsum as integer : lowestsum = 32767
dim highestsum as integer : highestsum = 0
dim currentsum as integer

' This will be used as an index into the sums array later on.
dim range as integer

' Assume we're reading the whole file..
do until eof(filenum)
' Indentation is good to clearly see the beginning and end of compound
' statements (like DO..LOOP, SELECT..END SELECT, procedure definitions,
' etc.). Code is hard to read in novel form. Whitespace is your friend.
input #filenum, currentdate, n1, n2, n3

' Only accept numbers from at least the earliest date. All of the summation
' and average calculations are inside this IF block, it would be nicer to
' have a CONTINUE DO, QB forces bad habits upon us..
if currentdate >= earliestdate then
' Notice that the sum is only calculated if indeed we accept the date.
' It's good to avoid doing unnecessary calculations whenever possible.
' As programs get more complex, this becomes more essential in creating
' clear and efficient code.
currentsum = n1 + n2 + n3

' Update lowest and highest sums..
if currentsum < lowestsum then lowestsum = currentsum
if currentsum > highestsum then highestsum = currentsum

' Update ranged sums..
if currentsum < 25 then
' For sums under 25, we can use the observation that each element in
' the sums array represents a range of 3 numbers. This is just a
' little math trick that gets the correct index into the array. It's
' good to notice when situations like this come up, it beats long IF
' or SELECT blocks.. get it in your head that code duplication is
' evil, and should be avoided at all costs !
range = int((currentsum + 2) / 3)
sums(range) = sums(range) + currentsum
else
sums(9) = sums(9) + currentsum
end if

sumcount = sumcount + 1
total = total + currentsum

print "date / numbers / sum / running avg. sum: " ;
print using "### / ###-,###-,### / ### / ###.##" ; currentdate ; n1;n2;n3 ; currentsum ; (total / sumcount)
end if
loop

close #filenum

' Output the average sums. Notice how using an array and a little math has
' reduced the amount of code needed for this. More sum ranges can be added
' without duplicating more PRINT statements. BTW, I'm not really sure what
' information you intended to be outputting here..
for range = 1 to 8
dim upperlimit as integer : upperlimit = range * 3
dim lowerlimit as integer : lowerlimit = upperlimit - 2
print "Total sums from" ; lowerlimit ; "to" ; upperlimit ; ": " ;
print using "###.##" ; (sums(range) / sumcount)
next
print "Total sums from 25 and above: " ;
print using "###.##" ; (sums(range) / sumcount)

print "Lowest/highest sum: " ; lowestsum ; "/" ; highestsum
print "Average sum for all dates: " ; (total / sumcount)

 
 Respond to this message   
AuthorReply
Solitaire
(Login Solitaire1)
S

Your initialization of highest and lowest is incorrect

August 27 2007, 11:25 AM 

> dim lowestsum as integer : lowestsum = 32767
> dim highestsum as integer : highestsum = 0

When you make the comparison to an array value using these figures, you will never be able to determine the highest or lowest numbers in your array.

What you need to do is select the first array value as the arbitrary highest and lowest value, and then compare each element in the array to that arbitrary value.

Suppose the array contains 9 elements:

lowestsum = myarray(1)
highestsum = myarray(1)
FOR x = 2 TO 9
   IF myarray(x) > lowestsum THEN lowestsum = myarray(x)
   IF myarray(x) > highestsum THEN highestsum = myarray(x)
NEXT x

 
 Respond to this message   

(Premier Login iorr5t)
Forum Owner

Good advice

August 27 2007, 11:46 AM 

And you've said it at least 10 times. And still I forget and the next time I need to do min/max I make a dumb assignment. Let's hope this time soaks in!

Mac

 


 
 Respond to this message   
Laanan Fisher
(no login)

Re: Your initialization of highest and lowest is incorrect

August 27 2007, 4:25 PM 

Gary's original code only kept the min/max values of the individual dates/numbers read from the file,

41 S = N1 + N2 + N3
...
58 IF S < S1 THEN S1 = S ' (Determines if the sum is the lowest)
59 IF S > S2 THEN S2 = S ' (Determines if the sum is the highest)

not the min/max of the array elements (which I incorrectly misread as totals, not as counters like his original code, my version should increment the array elements not add *currentsum*, sorry Gary). I'm still not sure exactly what this program is supposed to do, but your suggestion and my mistake result in different behavior of the original code. You make a good observation, though, but it all depends on what min/max you're actually looking for.

In any case, a check on sumcount should be added to my version to see if any dates/numbers were actually read from the file in order to interpret lowestsum and highestsum correctly - perhaps by displaying "N/A" if no dates/numbers were read.

 
 Respond to this message   
Laanan Fisher
(no login)

Re: Some advice for Gary

August 27 2007, 4:33 PM 

By the way, I probably misinterpretted the purpose of the S3 - S11 variables ( sums array ) by associating them with S1 and S2 variables ( lowestsum , highestsum ), which of course do hold individual dates/number sums.

An excellent reason to use more descriptive variable names: others may have a hard time keeping track of what all those letters and numbers are supposed to mean and get confused easily (like me).

 
 Respond to this message   
Current Topic - Some advice for Gary
  << Previous Topic | Next Topic >>Return to Index  
 Copyright © 1999-2014 Network54. All rights reserved.   Terms of Use   Privacy Statement  

Newbies usually go to www.qbasic.com and click on The QBasic Forum
Forum regulars have their own ways, which include The QBasic Community Forums