Programavimas

Dėmesio: „Java“ nuo dvigubo iki „BigDecimal“

Didelės pasaulinės „Java“ kūrėjų bazės ir lengvai prieinamos internetinės API dokumentacijos derinys leido iš esmės išsamų ir tikslų „Java SE“ API dokumentavimą. Vis dar yra kampų, kurie gali būti ne tokie išsamūs ar tikslūs, kaip norėtųsi, tačiau API dokumentacija paprastai yra gana gera tiek išsamumo, tiek tikslumo požiūriu.

Nors „Javadoc“ pagrindu sukurta API dokumentacija tapo gana naudinga, mes, kūrėjai, dažnai taip skubame ir dažnai jaučiamės tokie įsitikinę savo sugebėjimais, kad beveik neišvengiama, jog kartais ir toliau bandysime daryti dalykus, prieš tai neskaitydami vadovo. Dėl šios tendencijos retkarčiais galime sudegti neteisingai naudodami tam tikrą API, nepaisant to, kad dokumentai įspėja, kad taip (neteisingai) nenaudokite. Aptariau tai savo tinklaraščio įraše Boolean.getBoolean (String) ir išskyriau panašią šio įrašo problemą, susijusią su „BigDecimal“ konstruktoriaus naudojimu, kuris priima dvigubą.

Iš pirmo žvilgsnio gali pasirodyti, kad „BigDecimal“ konstruktorius, priėmęs „Java“ dvigubą versiją, visais atvejais laikytųsi iš pradžių nurodytu tikslumu. Tačiau „Javadoc“ pranešimas šiam konstruktoriui aiškiai įspėja: „Šio konstruktoriaus rezultatai gali būti kiek nenuspėjami“. Toliau paaiškinama, kodėl (dvigubai negali būti tikslus tikslumas ir tai akivaizdu perduodant „BigDecimal“ konstruktoriui) ir siūloma vietoj to naudoti alternatyvų konstruktorių, priimantį String kaip parametrą. Dokumentuose taip pat siūloma naudoti „BigDecimal.valueOf“ (dvigubą) kaip pageidaujamą būdą konvertuoti dvigubą arba „float“ į „BigDecimal“.

Toliau pateiktas kodų sąrašas naudojamas šiems principams ir kelioms susijusioms idėjoms parodyti.

„DoubleToBigDecimal.java“

importuoti java.math.BigDecimal; importuoti statinį java.lang.System.out; / ** * Paprastas pavyzdys problemų, susijusių su „BigDecimal“ konstruktoriaus naudojimu * priėmus dvigubą. * * //marxsoftware.blogspot.com/ * / public class DoubleToBigDecimal {private final static String NEW_LINE = System.getProperty ("line.separator"); public static void main (final String [] argumentai) {// // Parodykite BigDecimal iš double // final double primitiveDouble = 0,1; final BigDecimal bdPrimDoubleCtor = new BigDecimal (primitiveDouble); final BigDecimal bdPrimDoubleValOf = BigDecimal.valueOf (primitiveDouble); galutinė Dviguba nuoroda Dviguba = Dviguba vertė (0,1); final BigDecimal bdRefDoubleCtor = new BigDecimal (referenceDouble); final BigDecimal bdRefDoubleValOf = BigDecimal.valueOf (referenceDouble); out.println ("Primityvus dvigubas:" + primityvus dvigubas); out.println ("Reference Double:" + referenceDouble); out.println ("Primityvus BigDecimal / Double per Double Ctor:" + bdPrimDoubleCtor); out.println ("Nuoroda BigDecimal / Double per Double Ctor:" + bdRefDoubleCtor); out.println ("Primityvus BigDecimal / Double per ValueOf:" + bdPrimDoubleValOf); out.println ("Nuoroda BigDecimal / Double per ValueOf:" + bdRefDoubleValOf); out.println (NEW_LINE); // // Parodykite „BigDecimal“ iš plūdės // galutinis plūdės primityvusFloat = 0.1f; final BigDecimal bdPrimFloatCtor = new BigDecimal (primitiveFloat); final BigDecimal bdPrimFloatValOf = BigDecimal.valueOf (primitiveFloat); galutinė „Float referenceFloat“ = „Float.valueOf“ (0,1f); final BigDecimal bdRefFloatCtor = new BigDecimal (referenceFloat); final BigDecimal bdRefFloatValOf = BigDecimal.valueOf (referenceFloat); out.println ("Primityvi plūdė:" + primitiveFloat); out.println ("Reference Float:" + referenceFloat); out.println ("Primityvus BigDecimal / Float per Double Ctor:" + bdPrimFloatCtor); out.println ("Nuoroda BigDecimal / Float per Double Ctor:" + bdRefFloatCtor); out.println ("Primityvus BigDecimal / Float per ValueOf:" + bdPrimFloatValOf); out.println ("Nuoroda BigDecimal / Float via ValueOf:" + bdRefFloatValOf); out.println (NEW_LINE); // // Daugiau problemų, kylančių iš „float“ į dvigubą, įrodymų. // galutinis dvigubas primityvusDoubleFromFloat = 0,1f; galutinė dviguba nuorodaDoubleFromFloat = nauja dviguba (0,1f); galutinis dvigubas primitiveDoubleFromFloatDoubleValue = new Float (0.1f) .doubleValue (); out.println ("Primityvus dvigubas iš plūdės:" + primitiveDoubleFromFloat); out.println ("Standartinis dvigubas vaizdas iš plūdės:" + referenceDoubleFromFloat); out.println ("Primityvus dvivietis iš FloatDoubleValue:" + primitiveDoubleFromFloatDoubleValue); // // String naudojimas tikslumui palaikyti nuo „float“ iki „BigDecimal“ // galutinė eilutė „floatString“ = String.valueOf (nauja „Float“ (0,1f)); final BigDecimal bdFromFloatViaString = new BigDecimal (floatString); out.println ("BigDecimal iš Float per String.valueOf ():" + bdFromFloatViaString); }} 

Išvestis iš minėto kodo paleidimo rodoma kitame ekrano momentiniame vaizde.

Kaip rodo aukščiau pateiktas išėjimas, plūdės liejimo dvigubai problema neleidžia išlaikyti norimo tikslumo, kai plūdę praleidžia tiesiai į „BigDecimal.valueOf“ (dviguba) metodas. Stygas gali būti naudojamas kaip tarpininkas tam pasiekti, kaip parodyta pavyzdyje ir panašiai, kaip „Converting Float to Double“ ne taip įprastu būdu.

Atkreipkite dėmesį, kad sunkus „Groovy“ numanomas „BigDecimal“ naudojimas šiek tiek pakeičia žaidimą, kai naudojamas „Groovy“ ir dinaminis spausdinimas. Tai galiu paliesti būsimame tinklaraščio įraše. Norėdami gauti daugiau informacijos apie slankiojo kablelio problemas (ir aš pabrėžiu „detales“), žr. Ką kiekvienas kompiuterių mokslininkas turėtų žinoti apie slankiojo kablelio aritmetiką.

Šią istoriją „Atsargiai:„ Double to BigDecimal “Java“ iš pradžių išleido „JavaWorld“.

$config[zx-auto] not found$config[zx-overlay] not found