Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in the org.jorlib.alg.packing.circlePacking.util.sqrt(BigDecimal squarD, MathContext rootMC) method. #4

Open
MikhailZvagelsky opened this issue Apr 19, 2016 · 4 comments

Comments

@MikhailZvagelsky
Copy link

Dear Joris,
I've found that sqrt() method for BigDecimals sometimes not comply its contract.
For example,
let exactSqrt be BigDecimal represented by the string
String str = "0.352818528921979802147666515426902895727765101266038472739273675725801740461899203391467404999652538893639944052164993861983322930689421050680216977023059231670566602635420201308103469059177274411042449967235640170639404861525798685782654348576008053906678123883330032297238500985193573602497626771580945594770502324168762166567267289269665176402913948019856635315861428993880073282624381118485716289019571647659739495016074896218885978289930340857274515862259731833170589692399895634244147482703269890913247408478923447178902017779845443742308844558419999046111467812933248023432427998259994182648578288775189490102071574925542172618705808377981407075661662506742408661232720032172324989308087757531861080580705851938971046656424285025030048776692043487994681169121806548569325273977674268512834848319197541770346893931298171263359209287656256258646644947830231869419567842967424731270811652666974200603722897904972781881580215186731799243387581020765695927222985513092811072096813507351486163616474354491678516423019462856092324589467805417576434369118271125610599862858091034066115393896376402586115322883185629500789989825539099146963464597667690086645833677773341477425089421202029845828438186267290619982627882863531585505515611951359679835295645460495124946561810293085634756353824263832486284294130150330118760419800451287490407783325022093281030504666007839427958453674663221723404057631681719148427415412519993998928227188905950986505087130321733361332156307945821264095564986339643413952656671077302618008809419170629325044973291573447163149540989060334863465155227701549160360633076458829101325288181727254148455952801479839414624838237422509188727938777531618602609770842427633605357541405468766390741255444162263154213109493016536875507122768177992567211419631697956177013676147279765005362827247748175113476912061656596560057107219180031161086243871513570693257886733246854019430780326947936432096164343749503593404634630874853900858530925398333908462443249715617740821018862850469001766145798985952338158907879181848149273610535411146431164860190045987407079776737665145855618269772150097545656533084155333408671462357567952863327464733354130776616979840611935007402670571489089668548000566788250160846791012993775567439582182725205696062583108329707566149812378805220075179590531688600283608991116551549027626948019331454835003314143801424170814628183200055052199722542207640173290280989264977286415610857154441019808138140819856280410105031134448183196991569236564590128053475070955652666628369465344771805924916499026673246861918192823814334395024295138823232784709065496229159508579419100068387896656615250289291758465598666278370085239497533286365488975303055116815329102108942419789159408743304837147769168826679563309806682084876882871097306440805958691670681692306549364491345283413772350464609125873897690388407474850326909999101415928102266360806164931776847358063319741306986987628745641280473524000212369792965384091797156403233777795567784543089119411659393168440334248938741623001128517522693879403929699173451781412798671665283558729628243926890969910443705973489192155576353499381779194610671587110478486168711282156757950565546363036019684717556713624143788093810345688751549193665721896867887651320967000222128167164946865556889602661431879227060777814881492519547779448310707438750917861990561928144098861424157634058497094462991766917173509132343518475084202673630176061598854141914185610767706802039701642072360625842378688027735898240182190514393189209471611768527100950310316851880853478199424580668628085693182998731100236819825441203790704941193496754099933586278887732102406442366897274992111227286780538771607254703391727435908633086669314433562019482301856480278389899972125503889024035852303562592479624352423337002906871575935923566494087298753092343486998023539344694510533797805958900582731852193990439519387549384829431113980579322708657363957164395621754828226758348067425530114629280261288667931574298350041682965467047588359489270073143306999546737192711175822029705263447027865758551542802171488905955004349464501480093234324812778987292165459441941026474022142289145222953357220372418411212413061286574450794826437795190069128780886322873705075391534786287589843850190532006721823083493988784719966839685662262264057458858102263578441838880872379410128677308321014897665822450598742323482617706556668314972948257303337118691806018319646689269303327895611192483290610412447084434138915732180208661257866451990865563784573699574180113438083551175839547069343207045045995100912147324966281922502715105823762488576030121131547913526483123729519773892343318565326104868289395276455971388735259382226159413912984029551781738507760341551002029698244452208252501876382885200201519676863857276544629621043623553022169433277290829018245988763416544714675486727259277158207185683059120469903788050023125005340124434545488528442744313808998213896416775571508334831773577301265300131926124116720552814768332474881127016239632373827247236037212368475176197284063580380941316779730166327775936730580436889438218610438044839337499052077613183040131513844261362138421340482537949355008184657331131802878928188016227607049663793923496957161690184263051610305144160357410316194354127288952746801158072255627528356254285419729629914150135164293325498786148924752199146507320087447951639563162872093511891508859874602833528357633853230657750414976922360211994756093221208726220406868776436423802282853111630343720137345935295997001814433021729906260871559252222785750795910525236903608970515342971450150471140143424730302419832493045288822449089904121958127502411554916890000523296881346660246083743133530717406880789993705668249624474982096681744820733458578119329965309671669003956057605867177163829210966938191726511853645119095575338547037668182994797666943720389432824576727544324133629219070818056301690488891414444637139445286226789026200554535161974614349396819623126119487492383584029405209572120869911038247087356343641894799034464020392552038747499914221074709047988903494270079315963932888035593068602395612879290719088991015317352105164692480211676756550307172096101637696730714405029471608453893636023178565563010040550935381304155988922549067016051209896944367217070301142516901257757847663657027699473130521129513917273661361656490890291200300878354926042615514456147252662943337364841398596952462369372282916304134920158141647180675038504459880237319";
Then the code:

BigDecimal exactSqrt = new BigDecimal(str);
BigDecimal number = exactSqrt.multiply(exactSqrt);
MathContext mathContext = new MathContext(exactSqrt.precision() + 1, RoundingMode.HALF_UP);
BigDecimal rounded = exactSqrt.round(mathContext);
BigDecimal sqrt = MathUtil.sqrt(number, mathContext);
BigDecimal difference = rounded.subtract(sqrt);
BigDecimal scaledDifference = difference.scaleByPowerOfTen(difference.scale());
System.out.println("Scaled difference: " + scaledDifference.toPlainString());

produces
Scaled difference: -465100 instead of zero.

@jkinable
Copy link
Collaborator

jkinable commented Apr 19, 2016

Hi Mikhail,
Thanks for reporting this. This Math Utility was originally contributed by Frans Lelieveld, so I'm not very familiar with its implementation. Would you be able (and willing) to look into this issue and see whether this is actually a bug in the code, or for example a rounding issue? Your input is a very long number, and the scaled difference seems very small compared to the very big number you put in, so I wouldn't be surprised if this issue is caused by rounding.

@MikhailZvagelsky
Copy link
Author

MikhailZvagelsky commented Apr 21, 2016 via email

@MikhailZvagelsky
Copy link
Author

Joris, I found that the method gives wrong answer for the number 4 * 10^74 + 1 with rounding mode UP. The square root of this number exceeds 2 * 10^37, so correct UP rounding with 1 digit precision should be the number 3 * 10^37. But

BigDecimal number = new BigDecimal(new BigInteger("4"), -74).add(BigDecimal.ONE);
mathContext = new MathContext(1, RoundingMode.UP);
System.out.println(MathUtil.sqrt(number, mathContext).toPlainString());

produces 2E+37.

@jkinable
Copy link
Collaborator

Hm I agree with your example. It seems that this error occurs with very
tiny numbers. Given that you were able to study the book which was used to
implement this algorithm, would you be able to spot the implementation
issue? The book refers to an implementation itsqrt.cc, which you can find
on the publisher's website:
http://extras.springer.com/2001/978-3-642-56735-3/hfloat/hfloat/src/hf/itsqrt.cc
The first line states: "#warning 'sqrt_iteration() is experimental (loss
of precision !)'". So I'm not surprised that you encounter precision errors
with such small numbers. Here's another implementation:
https://github.com/rizar/matrix/blob/master/src/com/github/rizar/bigdecimalmath/BigDecimalMath.java
Does this one have similar issues?
I'm happy to help you out wherever I can, but I have very little knowledge
about this specific domain...

Joris

On Fri, Apr 22, 2016 at 9:40 AM, Mikhail Zvagelsky <[email protected]

wrote:

Joris, I found that the method gives wrong answer for the number 4 *
10^74 + 1 with rounding mode UP. The square root of this number exceeds 2

  • 10^37, so correct UP rounding with 1 digit precision should be the
    number 3 * 10^37. But

BigDecimal number = new BigDecimal(new BigInteger("4"),
-74).add(BigDecimal.ONE);
mathContext = new MathContext(1, RoundingMode.UP);
System.out.println(MathUtil.sqrt(number, mathContext).toPlainString());

produces 2E+37.


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
https://github.com/jkinable/jorlib/issues/4#issuecomment-213431613

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants