Programmēšana

Uzmanību: Java divkāršs līdz BigDecimal

Java lielās pasaules izstrādātāju bāzes un viegli pieejamās tiešsaistes API dokumentācijas kombinācija ir ļāvusi izveidot visaptverošu un precīzu Java SE API dokumentāciju. Joprojām ir stūri, kas, iespējams, nav tik pamatīgi vai precīzi, kā gribētos, taču API dokumentācija parasti ir diezgan laba gan pamatīguma, gan precizitātes ziņā.

Lai arī uz Javadoc balstītā API dokumentācija ir kļuvusi diezgan noderīga, mēs, izstrādātāji, bieži tik ļoti steidzamies un bieži vien jūtamies tik pārliecināti par savām spējām, ka ir gandrīz neizbēgami, ka mēs dažreiz turpināsim mēģināt darīt lietas, vispirms neizlasot rokasgrāmatu. Šīs tendences dēļ mēs laiku pa laikam varam sadedzināt, nepareizi lietojot konkrētu API, neskatoties uz dokumentāciju, kas brīdina mūs to (nepareizi) neizmantot šādā veidā. Es to apspriedu savā emuāra ziņojumā vietnē Boolean.getBoolean (virkne) un šajā ziņā izceļu līdzīgu problēmu saistībā ar BigDecimal konstruktora izmantošanu, kas pieņem dubultu.

No pirmā acu uzmetiena var šķist, ka BigDecimal konstruktors, kas pieņem Java dubultu, visos gadījumos to turētu ar sākotnēji norādīto precizitāti. Tomēr Javadoc ziņojums šim konstruktoram skaidri brīdina: "Šī konstruktora rezultāti var būt nedaudz neparedzami." Turpinājumā tiek paskaidrots, kāpēc (dubultniekam nevar būt precīza precizitāte, un tas ir skaidri redzams, kad tas tiek nodots BigDecimal konstruktoram) un tiek ieteikts tā vietā izmantot alternatīvo konstruktoru, kurš kā virkni pieņem virkni. Dokumentācijā ir arī ieteikts izmantot BigDecimal.valueOf (double) kā vēlamo veidu, kā pārveidot dubultu vai pludiņu par BigDecimal.

Lai parādītu šos principus un dažas saistītās idejas, tiek izmantots šāds kodu saraksts.

DoubleToBigDecimal.java

importēt java.math.BigDecimal; importēt statisko java.lang.System.out; / ** * Vienkāršs problēmu piemērs, kas saistīts ar BigDecimal konstruktora izmantošanu *, pieņemot dubultu. * * //marxsoftware.blogspot.com/ * / public class DoubleToBigDecimal {private final static String NEW_LINE = System.getProperty ("line.separator"); public static void main (final String [] argumenti) {// // Demonstrējiet BigDecimal no double // final double primitiveDouble = 0,1; gala BigDecimal bdPrimDoubleCtor = jauns BigDecimal (primitiveDouble); final BigDecimal bdPrimDoubleValOf = BigDecimal.valueOf (primitiveDouble); galīgā Double referenceDouble = Double.valueOf (0,1); galīgais BigDecimal bdRefDoubleCtor = jauns BigDecimal (referenceDouble); final BigDecimal bdRefDoubleValOf = BigDecimal.valueOf (referenceDouble); out.println ("Primitive Double:" + primitiveDouble); out.println ("Reference Double:" + referenceDouble); out.println ("Primitīvs BigDecimal / Double caur Double Ctor:" + bdPrimDoubleCtor); out.println ("Atsauce BigDecimal / Double caur Double Ctor:" + bdRefDoubleCtor); out.println ("Primitīvs BigDecimal / Double caur ValueOf:" + bdPrimDoubleValOf); out.println ("Atsauce BigDecimal / Double caur ValueOf:" + bdRefDoubleValOf); out.println (NEW_LINE); // // Demonstrējiet BigDecimal no pludiņa // final float primitiveFloat = 0.1f; gala BigDecimal bdPrimFloatCtor = jauns BigDecimal (primitiveFloat); final BigDecimal bdPrimFloatValOf = BigDecimal.valueOf (primitiveFloat); final Float referenceFloat = Float.valueOf (0.1f); final BigDecimal bdRefFloatCtor = new BigDecimal (referenceFloat); final BigDecimal bdRefFloatValOf = BigDecimal.valueOf (referenceFloat); out.println ("Primitīvais pludiņš:" + primitiveFloat); out.println ("Reference Float:" + referenceFloat); out.println ("Primitive BigDecimal / Float via Double Ctor:" + bdPrimFloatCtor); out.println ("Reference BigDecimal / Float via Double Ctor:" + bdRefFloatCtor); out.println ("Primitive BigDecimal / Float via ValueOf:" + bdPrimFloatValOf); out.println ("Atsauce BigDecimal / Float, izmantojot ValueOf:" + bdRefFloatValOf); out.println (NEW_LINE); // // Vairāk pierādījumu par problēmām, kas rodas no pludiņa līdz dubultai. // galīgais dubult primitīvsDoubleFromFloat = 0,1f; final Double referenceDoubleFromFloat = new Double (0,1f); final double primitiveDoubleFromFloatDoubleValue = new Float (0.1f) .doubleValue (); out.println ("Primitīvs dubultnieks no pludiņa:" + primitīvsDoubleFromFloat); out.println ("Atsauce Double no Float:" + referenceDoubleFromFloat); out.println ("Primitīvs Double no FloatDoubleValue:" + primitiveDoubleFromFloatDoubleValue); // // String izmantošana, lai saglabātu precizitāti no pludiņa līdz BigDecimal // galīgā virkne floatString = String.valueOf (new Float (0.1f)); final BigDecimal bdFromFloatViaString = new BigDecimal (floatString); out.println ("BigDecimal no Float caur String.valueOf ():" + bdFromFloatViaString); }} 

Iepriekš minētā koda palaišanas rezultāts tiek parādīts nākamajā ekrāna momentuzņēmumā.

Kā norāda iepriekšminētā izeja, pludiņa dubultās liešanas problēma neļauj saglabāt vēlamo precizitāti, pārejot pludiņu tieši uz BigDecimal.valueOf (dubultā) metodi. Stīgu var izmantot kā starpnieku, lai to paveiktu, kas parādīts piemērā un kas līdzīgā veidā parādīts, pārveidojot pludiņu uz dubultu ne tik bieži.

Ņemiet vērā, ka Groovy smagā netiešā BigDecimal izmantošana nedaudz maina spēli, izmantojot Groovy un dinamisko rakstīšanu. Iespējams, es to pieskaršos kādā nākamajā emuāra ziņā. Lai iegūtu sīkāku informāciju par peldošā komata jautājumiem (un es uzsveru "detaļas"), skatiet Kas katram datorzinātniekam būtu jāzina par peldošā komata aritmētiku.

Šo stāstu "Uzmanību: Double to BigDecimal Java" sākotnēji publicēja JavaWorld.

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