Page 1 of 2

divisible by 2

Posted: Sun Dec 14, 2008 6:23 pm
by qbasicfreak
This is really a dumb question but how can you check if a number is a multiple of 2? I've tried everything I could think of.

ie.
IF string% = 'divisible by 2' THEN

Thanks
Qbasicfreak

Posted: Sun Dec 14, 2008 6:48 pm
by Ralph
Try:

IF number/2 = INT(number/2) THEN

While a number may APPEAR to be difisible by two, it may have a very small error, and not be truly an even number. For example, it we test the result of 10 ^2 against 100, we get a remainder, thus, the second line below returns, "NOT AN EVEN NUMBER", since the number has a very small remainder that is not even

PRINT 10 ^ 2 - 100 'gives a remanider, so:
IF 10 ^ 2 / 2 = 50 THEN PRINT "OK" ELSE PRINT "NOT AN EVEN NUMBER"

USE MOD

Posted: Sun Dec 14, 2008 7:52 pm
by burger2227
MOD is Integer Remainder Division. When a whole number is odd, the remainder will be 1.

Code: Select all

 IF number MOD 2 = 0 THEN PRINT "Even" ELSE PRINT "odd"
Don't use that normal division verses Integer division stuff! Too cryptic.

As to exponents, just use a Single variable for the calculation. In QB, all numbers are single as default. You can define them otherwise using %, & or #.

variable = 10 ^ 2 ' undefined single variable

Then substitute that value to get rid of the small accuracy problems with Double values.

Ted

Posted: Mon Dec 15, 2008 5:24 am
by qbasicfreak
Thanks,
qbasicfreak

Posted: Mon Dec 15, 2008 11:04 am
by Ralph
That was good, Tec. I didn't understand your last part, the one about
variable = 10 ^ 2 ' undefined single variable

Then substitute that value to get rid of the small accuracy problems with Double values.
I entered"

Code: Select all

PRINT 10 ^ 2 - 100
and I got the remainder,
-6.928894E-18
indicating that 10 ^ 2 does not produce the exact value of 100 in QuickBASIC 4.5.

Running this code:

Code: Select all

FOR I = 1 TO 20
   PRINT I; I ^ 2 - I * I
NEXT I
RETURNS 0 FOR I = 1, 2, 3, 4, 6, 8, 12, and 16 only; all others give remainders. The numbers 1 through 20 either are treated as integers and the function is exact only in a few cases, or the numbers are single precision and the function returns the exact same value as the single numbers in a few cases. Sstrange. Is there an acceptable general answer that covers this?

Posted: Mon Dec 15, 2008 1:20 pm
by burger2227
PRINT will display the correct single value for any exponent calculation. To do that, just:

PRINT 5 ^ 2 'will display Single answer of 25

All you need to do is assign the exponent calculation to Single when doing calculations:

Code: Select all

FOR I = 1 TO 20 
   value! = I ^ 2     'get rid of small double inaccuracy
   PRINT I; value! - I * I 
NEXT I
If you are using DEFINT A-Z then you must assign the Single variable type with DIM or !

QB4.5 also has speed issues with complex Double calculations. There is a fix for it called FFIX. It is not necessary for your code however.

Ted

Posted: Mon Dec 15, 2008 9:45 pm
by Ralph
In the following code, I didn't actually use the ! to assign the single values, just the second line, "A = I ^ 2", and QB acts the same as in your example, but "I ^ 2" doesen't. Why? Is it that the default for any variable is single prexision, so that "A = number" will automatically make "number" a single precision number?

Code: Select all

FOR I = 1 TO 20
  A = I ^ 2
  PRINT I; A - 25; I ^ 2 - 25
NEXT I

Posted: Mon Dec 15, 2008 11:11 pm
by burger2227
When you are not using a DEF statement, all undefined variables default to Single values. That strips off any Double inaccuracies!

You are probably used to thinking that they are Integers. Single variables do not have the decimal point inaccuracies that Double values do. So Integer values are preserved in Single values.

Doubles can change the value 11 to 11.0000000001. That causes problems sometimes.

Ted

Posted: Tue Dec 16, 2008 11:00 pm
by Ralph
Ted, we're still not there. In the code, "FOR I = 1 TO 20", doesen't the vaiable I qualify for single precision assignment? If so, why does the example code in my previous post not give A 0 for "PRINT I ^ 2 - I* I" for all valuies of I? It does, but only for values of I of 1, 2, 3, 4, 6, 8, 12, and 16.

Posted: Tue Dec 16, 2008 11:31 pm
by burger2227
The variable used IN the calculation does not matter! It could be an Integer and still give you a Double inaccuracy.

Exponents always return Double values in QB.

Now if you assign the calculation to a Single variable, it is stripped of the small Double inaccuracy.

A = i% ^ 2 'is a Single variable value that will match an integer

Ted

Posted: Wed Dec 17, 2008 12:23 am
by Ralph
O.K. Then why does this give a small difference for ALL values of i for the first difference, and, except for i = 1.4 and 1.8, gives 0 for all other values of i for the second difference. ALL the values of i are single precision.

Code: Select all

FOR I = 1 TO 2 STEP 0.1
  A = I^2
  PRINT I, A-I*I, I^2 -I*I
NEXT I

Posted: Wed Dec 17, 2008 3:33 am
by burger2227
Those are small accuracy differences.........Real small! Try this:

Code: Select all

FOR I = 1 TO 2 STEP .1
  A = I ^ 2
  B = I * I
  PRINT I, A - B, (I ^ 2) - B
NEXT I
Now the differences are mostly in the second calculation. The Double one!

Ted

Posted: Wed Dec 17, 2008 5:08 am
by roy
Ralph, computers struggle with decimals because of the way that bits are divided into packets of eight. This program may show better the way that the computer handles Single,Double precision and decimals that are an eigth of 1.

CLS
DIM i AS DOUBLE
REM Using double precision with decimals, very messy.
FOR i = 1 TO 4 STEP .1
PRINT i,
NEXT
PRINT
REM Using single precision with decimals, some of the mess is removed.
FOR k = 1 TO 4 STEP .1
PRINT k,
NEXT
PRINT
REM Using a decimal that fits with the computers bit pattern, no problems.
FOR i = 1 TO 4 STEP .125
PRINT i,
NEXT
SYSTEM

Posted: Wed Dec 17, 2008 12:52 pm
by burger2227
Structure of QB Precision numbers:

Double precision (DOUBLE in QBASIC) 8 bytes = 64 bits:
Sign: 1 bit
Exponent: 11 bits
Mantissa: 52 bits

Single precision (SINGLE in QBASIC) 4 bytes = 32 bits:
Sign: 1 bit
Exponent: 8 bits
Mantissa: 23 bits

The mantissa holds all of the decimal point values. The Exponent of Single is 8 bits or ONE byte. Thus it does not have the same Double error problem.

Ted

Posted: Thu Dec 18, 2008 5:39 pm
by Ralph
Roy and Ted's explanations make some sense to me, but, why don't the following three FOR/NEXT loops give the identical exaxt values for ALL three cases? Notice that the first one gives exact values for 1 through 2.7, the second one for 1.5 through 2.5, and the last one for 2.3 through 2.7

Code: Select all

CLS
PRINT
REM Using single precision with decimals, some of the mess is removed.
DIM k AS SINGLE
FOR k = 1 TO 4 STEP .1
PRINT k,
NEXT

PRINT
FOR k = 2 TO 4 STEP .1
PRINT k,
NEXT
PRINT

PRINT
FOR k = 2.3 TO 4 STEP .1
PRINT k,
NEXT
PRINT

Posted: Fri Dec 19, 2008 4:22 am
by roy
I would not attempt to work out why or how a team of programmers came up with the logic that they did to solve this problem. If I set a problem that was unsolvable to four different teams and asked them to get the best solution, I would likely get four different solutions.

Posted: Fri Dec 19, 2008 1:23 pm
by burger2227
Because you are using tenths instead of eigth's as Roy explained before. The Single exponent value matches 8 bits as in this example:

Code: Select all

CLS
PRINT
REM Using single precision with decimals, some of the mess is removed.
DIM k AS SINGLE
FOR k = 1 TO 4 STEP .125
PRINT k,
NEXT

PRINT
FOR k = 2 TO 4 STEP .125
PRINT k,
NEXT
PRINT

PRINT
FOR k = 2.25 TO 4 STEP .125
PRINT k,
NEXT
PRINT
A tenth creates a Single accuracy error.

Ted

Posted: Fri Dec 19, 2008 10:14 pm
by Ralph
O.K/., I'll stop here, based on Roy's "back to reality" explanation, and on Ted's pieces of eight.

Posted: Fri Dec 19, 2008 10:19 pm
by moneo
qbasicfreak wrote:This is really a dumb question but how can you check if a number is a multiple of 2? I've tried everything I could think of.

ie.
IF string% = 'divisible by 2' THEN

Thanks
Qbasicfreak
Saying that a number is a multiple of 2 is the same as saying that the number is even.

Assuming that the number is a integer, here's a simple way of determining whether it is odd or even.

defint a-z
IF Number AND 1 THEN
PRINT "Number is odd"
ELSE
PRINT "Number is even"
END IF

However, this method will consider the Number zero as even.

How it works. If the low order bit of a number is a one, then the number is odd, otherwise it's even.
So, when you AND with a 1, if the low order bit of the Number is also a one, then the ressult of "Number AND 1" gives you a TRUE condition which means that the Number is odd. Otherwise, the low order bit is zero, which means that the Number is even.

Regards..... Moneo

Posted: Wed Dec 24, 2008 6:18 pm
by Ralph
Hello,, Moneo!

Here is another quirk I find in QuickBASIC 4.5.
I ran the code in G-W BASIC, and got Odd. 0, ODD, odd, 0, A is odd.
I ran the code in QuickBASIC and got Odd, -1.734723E-18, EVEN, even, -1.734723E-18, A is odd.

So, the value that qb returns for 5 ^ 2 is not truly the integer 25, since the above shows that the difference is not 0.

It seems to me that your use of AND to detect odd or even would not be proper in qb, since further use of 5 ^ 2 as an integer would not be true in qb.

To truly get the exact integer 25, I find that Ted's answer of assigning a variable to it, seems to be the only way to go.


[code[CLS
IF F ^ 2 AND 1 THEN PRINT "Odd" ELSE PRINT "Even"
PRINT 5 ^ 2 - 25
IF 5 ^ 2 - 25 = 0 THEN PRINT "ODD" ELSE PRINT "EVEN"
IF INT(5 ^ 2) - 25 = 0 THE PRINT "odd" ELSE PRINT "even"
A = 5 ^ 2
IF A = 25 = 0 THEN PRINT "A is odd" ELSE PRINT "A is even"