Xref: utzoo comp.bugs.sys5:551 comp.bugs.4bsd:970 Path: utzoo!attcan!uunet!husc6!bloom-beacon!gatech!ncsuvx!ece-csc!ncrcae!sauron!wescott From: wescott@sauron.Columbia.NCR.COM (Mike Wescott) Newsgroups: comp.bugs.sys5,comp.bugs.4bsd Subject: Re: division bug in dc(1) - FIX Summary: fix and test script included Message-ID: <1154@sauron.Columbia.NCR.COM> Date: 13 Sep 88 18:53:58 GMT References: <1153@sauron.Columbia.NCR.COM> Reply-To: wescott@sauron.Columbia.NCR.COM (Mike Wescott) Organization: Entry Level Systems Development, NCR Corp., Columbia, SC Lines: 211 In article <1153@sauron.Columbia.NCR.COM> I wrote: > dc(1) returns some bogus values. Try feeding this to dc. > 10 k 3041280 d * 3041280.0000000001 / p > The vanilla 4.3BSD and 5.3.x dc return something like > 3041280.0-4008922557 (note the bogus minus sign). The problem is in the div() routine. As stated in "DC - An Interactive Desk Calculator" by R. Morris and L. L. Cherry, "It [the next digit of the trial quotient] may turn out to be one unit too low, but if it is, the next trial quotient will be larger than 99 and this will be adjusted ..." It turns out that the vanilla 4.3BSD and SVR3 (SVR4 is rumored to be fixed) versions of dc do not alway adjust quite right, moreover there are occasions when the trial quotient is too large. The following patch contains a fix to a problem with scale computation previously posted by woetzel@gmdzi.UUCP (Gerd Woetzel) with a fix by Heinrich Schueth (schue%gmdzi@unido.UUCP). That posting also had a fix in the div() code that I have modified further to produce this fix. This patch may be applied to either 4.3BSD or S5R3 sources. A shar of a test script follows the patch. *** dc.c.orig Mon Sep 12 10:39:57 1988 --- dc.c Mon Sep 12 09:37:15 1988 *************** *** 72,83 **** binop('*'); p = pop(); sunputc(p); ! savk = sk1+sk2; ! if(savk>k && savk>sk1 && savk>sk2){ sk = sk1; if(skk && n>sk1 && n>sk2){ sk = sk1; if(sk= 0)divd->wt--; ! } ! if(divcarry != 0){ ! salterc(p,dig-1); ! salterc(divd,-1); ! ps = add(divr,divd); ! release(divd); ! divd = ps; } rewind(p); --- 665,688 ---- d += 100; carry = 1; } ! salterc(ps,d); } divcarry = carry; + if(divcarry != 0){ + dig--; + release(ps); + goto retrydiv; + } else if (d > 0) { + dig++; + release(ps); + goto retrydiv; + } + release(divd); + divd = ps; sbackc(p); salterc(p,dig); sbackc(p); ! if(--offset >= 0) divd->wt--; } rewind(p); # This is a shell archive. Remove anything before this line, then # unpack it by saving it in a file and typing "sh file". (Files # unpacked will be owned by you and have default permissions.) # # This archive contains: # dctest echo x - dctest cat > "dctest" << '//E*O*F dctest//' # dctest takes an optional argument of the program to be tested # if no arg is present then ./dc is used # Error in division. Found by schue%gmdzi@unido.UUCP (Heinrich Schueth) if [ $# = 1 ] then dc=$1 else dc=./dc fi echo "Test 1 (division): Result of expression is" (bc -c | ${dc}) <