Witblitz Posted December 13, 2013 Share Posted December 13, 2013 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! Quote Link to comment Share on other sites More sharing options...
Barand Posted December 13, 2013 Share Posted December 13, 2013 What values are you feeding into the function? Quote Link to comment Share on other sites More sharing options...
Witblitz Posted December 13, 2013 Author Share Posted December 13, 2013 (edited) 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. 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 December 13, 2013 by Witblitz Quote Link to comment Share on other sites More sharing options...
Ch0cu3r Posted December 13, 2013 Share Posted December 13, 2013 So for all intent and purpose 35 is after all the value. Its actually 35.24 but the int rounds it down to nearest integer. Are you sure that these are the same values from the original code on the older computer? Quote Link to comment Share on other sites More sharing options...
Witblitz Posted December 13, 2013 Author Share Posted December 13, 2013 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 Quote Link to comment Share on other sites More sharing options...
Barand Posted December 13, 2013 Share Posted December 13, 2013 seems to depend on where you do the rounding down $length = 1802; $pitch = 50; echo floor(floor(($length-10)/$pitch) - 0.; //---> 34 Quote Link to comment Share on other sites More sharing options...
Witblitz Posted December 13, 2013 Author Share Posted December 13, 2013 (edited) 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 December 13, 2013 by Witblitz Quote Link to comment Share on other sites More sharing options...
gizmola Posted December 26, 2013 Share Posted December 26, 2013 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) - .; or $NRSLATHOR = intval($LSLATVER / $PITCHVER) - .); 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. Quote Link to comment Share on other sites More sharing options...
rbrown Posted December 28, 2013 Share Posted December 28, 2013 (edited) 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 December 28, 2013 by rbrown Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.