将大双倍转换为长双精度时的精度损失

时间:2015-10-27 16:22:18

标签: java math casting

我正在尝试将BigDouble转换为long(如标题中所述)。

class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        double test = Math.pow(Math.sqrt(5)+1,100);
        System.out.println("Double value : " + test);
        System.out.println("Long value : " + (long)test);
        System.out.println("BigInteger value : " + BigDecimal.valueOf(test).toBigInteger());
    }
}

double值为:1.0040690755570702E51

long值为:9223372036854775807

BigInteger值为:1004069075557070200000000000000000000000000000000000

我是否有办法将double值转换为long而不会失去那么多精度? (我知道小数将被截断,我不关心小数的精度)。

1 个答案:

答案 0 :(得分:3)

您可以使用BigDecimal完全执行数学运算。请注意,5的平方根是不合理的,只能用Math.sqrt近似。

BigDecimal bd = new BigDecimal(Math.sqrt(5));
bd = bd.add(BigDecimal.ONE);
bd = bd.pow(100);
System.out.println(bd);

这将获得带小数的值。它最终终止,因为Math.sqrt(5)的二进制表示终止。

1004069075557070220314035127599869875232877347832248.335614083066999226277233636952892814153487123118511103836542072361651874364047590617185064329712229035781817913394129062692739058485165256243993264883403592255060039960606356318602881236662752264193185464261106016928587065881165917621943427715779807439912567006786556544167779878765695427214853896155495155544779015551636519167305821977226266172677351099520870637345821956925515872168273066845466529353560825919886348254491420741254651029517257638347173927688842962355076977017211947878337642573343335320563626414773318485730302465582963531958302150632885302272119976966868131568412390403857634526357234988963307846721182400156172821547144396516543971967260995129622390142937276143511132378122499239892321882311740661880283833277274555362473616210620936302856378920188036133160791858134109694669435975803580126975968735898681527753926445845317342286170889507945660832443620304894211069322767749637550156232843630937898403875735111247818990305045177239319107937666104892349791492927044252880117085561500930701649929408163224686487891491195890869963879317936209033887768705599320428587186820585124477819233881677169413943248337033821952045300614076624360507030899388499001449537809993551179651725122042920587138455751534442625834380046862038997969330295044399865997500324509791427402993609703116532721896605144620964845349270449593710577131502482627253093533564469467549780061749270325156415711518453596263182041192338956590551385046194905796043209908582811568469855538550464527622526751347104256930755850367104778821957555104866490750005374880982469542984160228032536802870363759249998505891306946079685846134825080307689947264421931831935790646845530408907825029615481506680531528592294080059161873180912306482424749245176486043648531983053682371807353129581274293613969906336417782479640182548883893228708674288495023471997951870871544011452907540696666330703231644342320149526606166664952289397323124556850148055258185846112257085001175509574350805431744072781908661050376668320741100987458191848591561906110751240283802811458053429159113781740828312285312936983426057041564056068935807267749389756678401028654049703609285847883001985191684395871992902257378258288533122787122353626521578789782114911137504485462276159452618800467883101132828381714999415045853379520937106253408643908805954348339210957624888846901261828322143843368597652857199970810347530186137617792631249042052591405763920208210951482606772387977041538402706259438726612053771211514174381446851051480905243667760613790410674913636167847698645435680029698424403763008267915725308540489216552252638583451767312519756190475210558106520439612189326469685055631390328305313658032594161727077359445171799354635101595380479852110429310472451904977511865562089935117652740357200154396149141677590561533870142186340857527278088267884738986596020549883882990862305420244489248891297594759583852802082947379067776055897879995666610689931035065780733115151992626195794633849410657293236559422123191923957415623521366516414816462964656077270025042620950882800429487647591386176722459728948133153252771094662415613376215358948107181072694112047909973224056298949245497104901740845885309701949809534991043680184774695498600309229429908217064306450797543962751987919659673496393371462222511537496854397100635962225117381208554447246753369523192049409076270030796623626905874120238163249641852420688430566582702488360426451115878582301467520493875091767739743112474053459932444948330101045594379930348275705111840035467125436970694481268140784129930080221721368480770545431406539853231328381758318976496825840364028158148542117577520959185058067111089524257105157800071926526406923176323264281447918834552000885496942558908039812339654674959404861066240651707107079174813973338975185375494633928783114906489048664628853421466019504976682194920970276980601575237026832624543241785098745371972244532325090053229376494349045145743780096462214430802793711416576152730191792894301099887833193148651049464794844792338183170944814413399597579539475360458119965648773366257104886250677499080819715127358327341611560843026321510753301578879963870620385298493343781871166954241913395901864488384710785812778587941204458510088425750854422608444718053452916520709579268798668801261474670807670127434922768285582208904700497107016976144160633695079180048858384491865073150088007746371629592104369628809254108031184347942163467655251516986409452324711711609456646082876872494842208318896552475731971315280176017368114560082400299526927874652828691718511017703484327643422585291529034156349763651374343662211937932267911888759933603178459347478392866404585070374111522100639658584899540642595811743965736244746419774290804585243755052044066806555684047598132452154764549882937341074806407079786350149796225160264166926561701931319703362532891333103179931640625

您可以通过调用round删除小数点以外的部分。使用精度52,因为小数点左边有52位数。

bd = bd.round(new MathContext(52, RoundingMode.HALF_EVEN));
System.out.println(bd);

输出:

1004069075557070220314035127599869875232877347832248

修改

现在更精确,但它不比double精度准确。我正在使用Newton-Raphson square root method for BigDecimals来更精确地计算出来; Java的sqrt中没有BigDecimal方法。

bigSqrt方法来自我上面链接的SO问题。

MathContext mc = new MathContext(52, RoundingMode.HALF_EVEN);
BigDecimal bd = new BigDecimal(5);
bd = bigSqrt(bd);
bd = bd.add(BigDecimal.ONE);
bd = bd.pow(100, mc);
System.out.println(bd);

输出:

1004069075557066849421378481393742434871238538784961