Jump to content

Failing to replicate BASIC INT() division as PHP code


Recommended Posts

I have a serious mathematical problem. I'm no expert in mathematics so I hope someone can take a look.

 

What it boils down to I have this line of BASIC code :

NRSLATHOR=INT(LSLATVER/PITCHVER-.

Let me first explain what that does. It's a simple equation to work out a base number of slats. It's the length of a slat divided by the (set pitch minus the material width). This program has been working fine for years as is.

 

Now when I re-wrote the overall program I came up with this line of PHP :

$NRSLATHOR = (int)((int)($LSLATVER / $PITCHVER) - .;

This was as an attempt to replicate the BASIC Integer Division with round down as it seems. I've also tried numerous other methods of floor(), ceil(), round() to get the expected result but I simply cannot replicate the BASIC result!

 

For most cases the result works, but now and then when we feed different values to it, it will not calculate the quantity correctly, and it would in essence break everything else.

 

For example: The original BASIC equation would return a value of 34 but the PHP would return a value of 35 and it would affect everything else after that and is in a state of mess.

 

I've broken down the functions and placed everything in a single page with echos and remarks for you to see the process, run the code (press F9) from : http://phpfiddle.org/main/code/nz9-ghm

 

The original PHP function to calculate the slat qty is :

  function tep_calc_slat_qty($length, $pitch, $screen_qty = '') {
  	$tolerance 		= $pitch + 2;
	$length 		= (int)$length - 10;
	$slat_qty		= (int)((int)($length / $pitch) - .; //not getting the expected result!
	
		do {
        	$pitch = ($length / ($slat_qty + 1));
        	$length = $pitch * ($slat_qty + 1);	
			if($pitch > $tolerance) { 
				++$slat_qty;
        	}
		} while($pitch > $tolerance);
		
	if ($screen_qty <> 1) {
		$slat_qty = $slat_qty * $screen_qty;
	}
	
	return $slat_qty;
  }

Any help appreciated!

Same as these : http://phpfiddle.org/main/code/nz9-ghm

 

Or:

$length = 1812;
$width = 50;

I just ran the BASIC code and it returned 35 instead of 34 so I'm stumped atm as to why the original program running on an older computer yields 34.

 

u0zutFE.jpg

 

So for all intent and purpose 35 is after all the value. Keep in mind I had to subtract 10 as per the original BASIC program before I do the calc.

Edited by Witblitz

Yes absolutely.

 

Here is the original code, pay attention to line 350 and 360, that is the bit that calcs the number of slats for both horizontal and vertical, yet the old program running on the older computer yields 34 in that particular case. That's why I'm stumped as to what the cause might be:

10  'start
20 KEY OFF:PI=3.141593:WIDTH LPRINT 110:LPRINT CHR$(27);CHR$(33);CHR$(5):CLS
30 WIDTHB=VAL(WIDTHB$):WIDTHT=VAL(WIDTHT$)
40 'PITCH=38.9:GOTO 180
50 CLS:LOCATE 1,1,:INPUT "NEAREST HORIZONTAL PITCH REQUIRED    ";PITCHHOR
60     IF PITCHHOR>71 OR PITCHHOR<20 THEN BEEP:GOTO 50
70     LOCATE 2,1,:INPUT "SLATTYPE OF HORIZONTAL VANE  ";HVTYPE
80     IF HVTYPE =1 OR HVTYPE=2 THEN 90 ELSE BEEP:GOTO 70
90 LOCATE 3,1,:INPUT "NEAREST VERTICAL PITCH REQUIRED      ";PITCHVER
100    IF PITCHVER>71 OR PITCHVER<20 THEN BEEP:GOTO 90
110    LOCATE 4,1,:INPUT "SLATTYPE OF VERTICAL VANE    ";VVTYPE
120    IF VVTYPE =1 OR VVTYPE=2 THEN 130 ELSE BEEP:GOTO 90
130    LOCATE 5,1,:INPUT "END FINSH TYPE A OR B        ";EFTYPE$
140    IF EFTYPE$="A" OR EFTYPE$="B" THEN 150 ELSE BEEP:GOTO 130
150    LOCATE 6,1,:INPUT "CONTINU Y/N ";CONTI$ :IF CONTI$="N" THEN RUN"NEWPRO"
152 CLS:LOCATE 7,1,:INPUT "WIDTH OF SCREEN AT THE BOTTOM";WIDTHB$
160    WIDTHB=VAL(WIDTHB$):IF WIDTHB=0 THEN BEEP:GOTO 2410
162 IF RECTANGLE$="Y" THEN 180
170    LOCATE 8,1,:INPUT "WIDTH OF SCREEN AT THE TOP   ";WIDTHT$
180 WIDTHT=VAL(WIDTHT$):IF WIDTHT$="0" THEN 200
190    IF WIDTHT=0 THEN WIDTHT=WIDTHB
200    LOCATE 9,1,:INPUT "HEIGHT OF SCREEN             ";HEIGHT1$
210    HEIGHT1=VAL(HEIGHT1$):IF HEIGHT1=0 THEN BEEP:GOTO 200
212 IF RECTANGLE$="Y" THEN 260
220    LOCATE 10,1,:INPUT "ANGLE AT LEFT HAND BOTTOM    ";ANGLL
230 IF WIDTHB=WIDTHT  THEN 260
240 IF WIDTHT>0 AND ANGLL=0 THEN 250 ELSE 260
250 ANGLL=ATN(HEIGHT1/((WIDTHB-WIDTHT)/2))*180/PI:SHAPE$="SYM":GOTO 270
260    IF ANGLL=0 THEN ANGLL=90
270    LOCATE 12,1,:PRINT "TYPE OR DESCRIPTION OF SCREEN";
280    LOCATE 13,1,:LINE INPUT DES$
290    LOCATE 15,1,:INPUT "NUMBER OF SCREENS OF THIS TYPE";NRSCREEN
300 IF NRSCREEN=0 THEN NRSCREEN=1
320 CLS:LSLATHOR=WIDTHB -10:LSLATVER=HEIGHT1-10
340 IF WIDTHB=WIDTHT AND ANGLL=90 THEN RECTANGLE$="Y" ELSE RECTANGLE$=""
350 NRSLATHOR=INT(LSLATVER/PITCHVER-.
360 NRSLATVER=INT(LSLATHOR/PITCHHOR-.
370 PITCHHOR=(LSLATHOR/(NRSLATVER+1)):LSLATHOR=PITCHHOR*(NRSLATVER+1)
372 IF PITCHHOR>72 THEN NRSLATVER=NRSLATVER+1:GOTO 370
380 PITCHVER=(LSLATVER/(NRSLATHOR+1)):LSLATVER=PITCHVER*(NRSLATHOR+1)
382 IF PITCHVER>72 THEN NRSLATHOR=NRSLATHOR+1:GOTO 380
392 IF EFTYPE$="A" THEN NRSLATHOR=NRSLATHOR+1:NRSLATVER=NRSLATVER+1
420 IF RECTANGLE$="Y" THEN 440 ELSE 660
440 IF HVTYPE=1 THEN SPACINGH=PITCHHOR-72.8 ELSE SPACINGH=PITCHHOR-92.5
442 IF VVTYPE=1 THEN SPACINGV=PITCHVER-72.8 ELSE SPACINGV=PITCHVER-92.5
450  IF SPACINGH<0 THEN SPACINGH=SPACINGH+PITCHHOR:GOTO 450
460  PRINT SPACINGV:IF SPACINGV<0 THEN SPACINGV=SPACINGV+PITCHVER:GOTO 460
470  IF EFTYPE$="B" THEN 490
480  SPACINGH=SPACINGH+PITCHHOR/2:SPACINGV=SPACINGV+PITCHVER/2
490  IF SPACINGH>PITCHHOR THEN SPACINGH=SPACINGH-PITCHHOR
500  IF SPACINGV>PITCHVER THEN SPACINGV=SPACINGV-PITCHVER
510 SPACINGH=INT(10*SPACINGH)/10:SPACINGV=INT(10*SPACINGV)/10
520 LPRINT "":LPRINT STRING$(90,205):PITCHH=INT((10*PITCHHOR)+.5)/10
522 PITCHV=INT((10*PITCHVER)+.5)/10
532 NETW=INT(LSLATHOR+10):NETH=INT(LSLATVER+10)
533 LPRINT "TYPE ";DES$;"  ";
534 LPRINT "  QUANTIY";NRSCREEN;
536 LPRINT "  WIDTH x DROP ";NETW;"x";NETH:LPRINT ""
538 LPRINT "HORIZONTAL SLATS  TYPE ";HVTYPE;
540 LPRINT "  LENGTH ";LSLATHOR-4,"PITCH ";PITCHH,"TOOLSET ";SPACINGH;
542 LPRINT "  END FINISH ";EFTYPE$:LPRINT ""
548 LPRINT "VERTICAL SLATS  TYPE ";VVTYPE;
560 LPRINT "  LENGTH ";LSLATVER-4,"PITCH ";PITCHV,"TOOLSET ";SPACINGV;
562 LPRINT "  END FINISH ";EFTYPE$:LPRINT "":LPRINT ""
564 LPRINT "HORIZONTAL SLATS  QTY ";NRSLATHOR*NRSCREEN,
566 LPRINT "VERTICAL SLATS  QTY ";NRSLATVER*NRSCREEN,
600 SLAT=INT(((NRSLATHOR*LSLATHOR)+(NRSLATVER*LSLATVER))/200+.5)/10
610 SURR=INT(((LSLATHOR+15)+(LSLATVER+15))/50+.5)/10
620 LPRINT "STRIP 111 x .6 ";NRSCREEN*SLAT;" m":LPRINT ""
630 LPRINT "SURROUND  ";NRSCREEN*SURR;" m",
640 LPRINT "CORNER BRACKETS ";NRSCREEN*4 ;" pcs":LPRINT STRING$(90,205)
650 LPRINT "":LPRINT "":GOTO 150

That did it, but then I get other instances where I'm out by 1 slat on other tickets. I'll have to rethink the entire mathematical process to get the results I want.

 

But thanks for looking at it. Much obliged.

Edited by Witblitz
  • 2 weeks later...

Your orginal basic code is doing this:

 

int(float/float - float)

 

A cast to int is going to be equivalent to a php cast to int or the use of intval, in that it discards the floating point portion of the result.

 

So either:

 

 

$NRSLATHOR = (int)($LSLATVER / $PITCHVER) - .8);

 

or

 

 

$NRSLATHOR = intval($LSLATVER / $PITCHVER) - .8));

 

I would probably opt for the 2nd option in your case.

 

If you're not getting the same result, then it's a case of the floating point defaults in use by each implementation creating rounding errors of slightly different proportions.

 

Just FYI, don't sprinkle so many typecasts into your PHP code.  If you start with an integer (no decimal point) then it's an int.  PHP will typecast using the rules described here:

 

http://www.php.net/manual/en/language.types.type-juggling.php

 

If you're getting odd results, you want to look at the intermediary results of the floating point operations and how rounding is occurring, rather than looking at the truncation, which is very simple.

 

In the case of both your original basic program, and the php program, use of floating point numbers have reliability issues:  http://www.php.net/manual/en/language.types.float.php

 

This paper gets pretty heady very quickly, but goes into more detail:  http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

 

My guess is that you are encountering the differences between how your old basic program handles floating point rounding errors, and how php is handling it on the operating system you are running under. 

 

 

Floating point numbers have limited precision. Although it depends on the system, PHP typically uses the IEEE 754 double precision format, which will give a maximum relative error due to rounding in the order of 1.11e-16. Non elementary arithmetic operations may give larger errors, and, of course, error propagation must be considered when several operations are compounded.

It has been since the late 70's, early 80' that I programmed basic.., so I'm trying get the cobwebs out...

Happens when you get old... (57)

 

In basic, the int() command rounds a number down to the nearest integer less than or equal to the number

So after it does this:

(LSLATVER/PITCHVER-.08)

it rounds it down

So this is how it should work.

$length = 1802;
$pitch = 50;
echo floor(($length-10)/($pitch-.08));

You need to force the operator precedence using "floor" otherwise you will get wrong results.

Or do the substraction outside first.

 

 

The next thing you are missing in your php function is, that on lines 372 and 382 in the basic program is doing this:

if the PITCHHOR or PITCHVER is greater than 72 (on both lines)

then it is adding 1 to the var on that line then going back to and doing the full line

(colon is used as a separator between the statements or instructions in a single line)

PITCHHOR=(LSLATHOR/(NRSLATVER+1)):LSLATHOR=PITCHHOR*(NRSLATVER+1)

Or

PITCHVER=(LSLATVER/(NRSLATHOR+1)):LSLATVER=PITCHVER*(NRSLATHOR+1)

 

so after Line 564 it changes the values based on the input.

 

That is why some of your answers are off depending on what values you input.

Edited by rbrown
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.