ජාවා හි දශම ස්ථාන දක්වා සංඛ්‍යාවක් වට කරන්නේ කෙසේද


1272

මා කැමති දෙය අර්ධ-අප් ක්‍රමය භාවිතා කරමින් දෙගුණයක් නූල් බවට පරිවර්තනය කිරීමේ ක්‍රමයකි - එනම් වටකුරු කළ යුතු දශම 5 නම්, එය සෑම විටම ඊළඟ අංකයට රවුම් වේ. බොහෝ අවස්ථාවන්හිදී බොහෝ දෙනා අපේක්ෂා කරන වටකුරු කිරීමේ සම්මත ක්‍රමය මෙයයි.

සැලකිය යුතු ඉලක්කම් පමණක් ප්‍රදර්ශනය කිරීමට මම කැමැත්තෙමි - එනම් පසුපස ශුන්‍යයන් නොතිබිය යුතුය.

මෙය සිදු කිරීමේ එක් ක්‍රමයක් වන්නේ ක්‍රමය භාවිතා කිරීමයි String.format:

String.format("%.5g%n", 0.912385);

ප්‍රතිලාභ:

0.91239

එය විශිෂ්ටයි, කෙසේ වෙතත් එය සෑම විටම දශම ස්ථාන 5 ක් සහිත සංඛ්‍යා සැලකිය යුතු නොවුනත් පෙන්වයි:

String.format("%.5g%n", 0.912300);

ප්‍රතිලාභ:

0.91230

තවත් ක්‍රමයක් නම් DecimalFormatter:

DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);

ප්‍රතිලාභ:

0.91238

කෙසේ වෙතත් ඔබට පෙනෙන පරිදි මෙය අර්ධ-වටකුරු භාවිතා කරයි. එනම් පෙර ඉලක්කම් ඉරට්ටේ නම් එය වටයනු ඇත. මම කැමති දේ මෙයයි:

0.912385 -> 0.91239
0.912300 -> 0.9123

ජාවා හි මෙය සාක්ෂාත් කරගත හැකි හොඳම ක්‍රමය කුමක්ද?


හායි, මම හිතුවා ඔබේ ලිපියේ මගේ වර්තමාන ගැටලුවට පරිපූර්ණ විසඳුමක් මම සොයාගෙන ඇති බව. මට හරියටම ඉලක්කම් 8 සිට දෙගුණයක් වට කිරීමට අවශ්‍යයි. එබැවින් මම String.format ("%. 8g", 0.000987654321) භාවිතා කළෙමි. එහි ප්‍රති result ලය 0,00098765432 වන අතර එය පෙනෙන්නේ ජාවා පළමු ශුන්‍ය නොවන ඉලක්කම් වලින් පසුව පැටලීමට පටන් ගන්නා බවයි. මේ සඳහා පහසු විසඳුමක් තිබේද?
tifi90

Answers:


764

භාවිතය setRoundingModeනියම වූ, RoundingModeපසුව, අර්ධ පවා වටය සමග ඔබගේ ගැටලුව හැසිරවීමට ඔබගේ අවශ්ය ප්රතිදානය සඳහා ආකෘතිය රටාව භාවිතා සුවිශේෂව.

උදාහරණයක්:

DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
    Double d = n.doubleValue();
    System.out.println(df.format(d));
}

ප්‍රතිදානය ලබා දෙයි:

12
123.1235
0.23
0.1
2341234.2125

සංස්කරණය කරන්න : මුල් පිළිතුර ද්විත්ව අගයන්හි නිරවද්‍යතාවයට ආමන්ත්‍රණය නොකරයි. එය ඉහළට හෝ පහළට වේවා යන්න ගැන ඔබ එතරම් තැකීමක් නොකරන්නේ නම් එය හොඳයි. නමුත් ඔබට නිවැරදි වටකුරු කිරීමක් අවශ්‍ය නම්, ඔබ අපේක්ෂා කරන අගයන්හි නිරවද්‍යතාවය සැලකිල්ලට ගත යුතුය. පාවෙන ලක්ෂ්‍ය අගයන්ට අභ්‍යන්තරව ද්විමය නිරූපණයක් ඇත. එයින් අදහස් වන්නේ 2.7735 වැනි අගයකට ඇත්ත වශයෙන්ම එම නිශ්චිත අගය අභ්‍යන්තරව නොමැති බවයි. එය තරමක් විශාල හෝ තරමක් කුඩා විය හැකිය. අභ්‍යන්තර අගය තරමක් කුඩා නම් එය 2.7740 දක්වා වට නොවනු ඇත. එම තත්වයට පිළියමක් ලෙස, ඔබ වැඩ කරන සාරධර්මවල නිරවද්‍යතාවය පිළිබඳව ඔබ දැනුවත් විය යුතු අතර, වට කිරීමට පෙර එම අගය එකතු කිරීම හෝ අඩු කිරීම. නිදසුනක් ලෙස, ඔබේ අගයන් ඉලක්කම් 6 ක් දක්වා නිවැරදි බව ඔබ දැනගත් විට, අර්ධ-මාර්ග අගයන් වට කිරීමට, එම නිරවද්‍යතාව අගයට එක් කරන්න:

Double d = n.doubleValue() + 1e-6;

වටය සඳහා, නිරවද්‍යතාවය අඩු කරන්න.


9
මෙතෙක් ඉදිරිපත් කර ඇති හොඳම විසඳුම මෙය විය හැකිය. මම පළමු වරට ඩෙසිමල් ෆෝමැට් පන්තිය දෙස බැලූ විට මෙම පහසුකම හඳුනා නොගැනීමට හේතුව එය හඳුන්වා දී ඇත්තේ ජාවා 1.6 හි පමණි. අවාසනාවට මට 1.5 භාවිතා කිරීමට සීමා වී ඇති නමුත් අනාගතය දැන ගැනීම ප්‍රයෝජනවත් වනු ඇත.
ඇලෙක්ස් ස්පර්ලින්

1
මම මෙය උත්සාහ කළේ "#.##":, වටකුරු HALF_UP. 256.335f-> "256.33"... (උදාහරණ අදහස් දැක්වීම් වලින් @ ඇස්ටරයිට්ගේ පිළිතුර දක්වා).
බිග්ස්ටෝන්

6
DecimalFormat ඔබගේ වර්තමාන දේශීය වින්‍යාසය මත රඳා පවතින බැවින් කරුණාකර ප්‍රවේශම් වන්න, ඔබට බෙදුම්කරුවෙකු ලෙස තිතක් නොලැබෙනු ඇත. මම පෞද්ගලිකව පහත දැක්වෙන්නේ ඇස්ටරයිට්ගේ පිළිතුරටයි
ගොමිනෝ

1
DecimalFormat නූල් ආරක්ෂිත යැයි ඔබ අපේක්ෂා නොකළ යුතු බව මතක තබා ගන්න. අනුව ජාවා ලේඛන : දශම ආකෘති සාමාන්යයෙන් සමමුහුර්ත නැත. එක් එක් නූල් සඳහා වෙනම ආකෘති අවස්ථා නිර්මාණය කිරීම රෙකමදාරු කරනු ලැබේ. බහු නූල් සමගාමීව ආකෘතියකට ප්‍රවේශ වන්නේ නම්, එය බාහිරව සමමුහුර්ත කළ යුතුය.
සී.ජී.කේ.

1
එය නිසි වටයක් සිදු වන පරිදි මා එය කරන්නේ කෙසේද, එවිට එය 0.0004 සිට 0.001 දක්වා වට නොවනු ඇත

475

උපකල්පනය valuea double, ඔබට කළ හැකිය:

(double)Math.round(value * 100000d) / 100000d

එය ඉලක්කම් 5 ක නිරවද්‍යතාව සඳහා ය. ශුන්‍ය ගණන දශම ගණන දක්වයි.


72
යාවත්කාලීන කිරීම: ඩෙසිමල් ෆෝමැට් භාවිතා කරනවාට වඩා මෙය සිදු කිරීම වේගවත් බව මම දැන් තහවුරු කළෙමි. මම DecimalFormat 200 වතාවක් භාවිතා කළෙමි, මෙම ක්‍රමය. ලූප 200 සම්පූර්ණ කිරීම සඳහා දශම ෆෝමැට් 14ms ගත වූ අතර මෙම ක්‍රමය 1ms ට වඩා අඩු විය. මා සැක කළ පරිදි මෙය වේගවත් ය. ඔරලෝසු චක්‍රයෙන් ඔබට මුදල් ලැබෙන්නේ නම්, ඔබ කළ යුත්තේ මෙයයි. මට පුදුමයි ක්‍රිස් කුඩ්මෝර් අවංක යැයි පැවසූ දේ පවා කියයි. ප්‍රාථමිකයන් වාත්තු කිරීමට හා දශම ෆෝමැට්.ෆෝමැට් () ට වඩා ස්ථිතික ක්‍රම (Math.round () භාවිතා කිරීමට වඩා වස්තු වෙන් කිරීම සැමවිටම මිල අධිකය.
ඇන්ඩි ජේ

100
මෙම තාක්ෂණය 90% කට වඩා අසමත් වේ. -1.
ලෝර්න් හි මාක්විස්

25
ඇත්ත වශයෙන්ම, මෙය අසමත් වේ : Math.round(0.1 * Math.pow(10,20))/Math.pow(10,20) == 0.09223372036854775.
රොබට් ටුපෙලෝ-ෂ්නෙක්

54
මෙම ක්‍රමය භාවිතා කරන විට (හෝ පාවෙන ස්ථානවල ඕනෑම වටයක්) භාවිතා කිරීමේදී ඉතා ප්‍රවේශම් වන්න. එය 265.335 තරම් සරල දෙයකට අසමත් වේ. 265.335 * 100 (ඉලක්කම් 2 ක නිරවද්‍යතාව) අතරමැදි ප්‍රති result ලය 26533.499999999996 වේ. මෙයින් අදහස් වන්නේ එය 265.33 දක්වා වටවී ඇති බවයි. පාවෙන ලක්ෂ්‍ය සංඛ්‍යා සිට සැබෑ දශම සංඛ්‍යා බවට පරිවර්තනය කිරීමේදී ආවේනික ගැටලු තිබේ. EJP ගේ පිළිතුර ಇಲ್ಲಿ stackoverflow.com/a/12684082/144578 බලන්න
සෙබස්තියන් වැන් ඩෙන් බ්‍රෝක්

6
E සෙබස්තියන්වාන්ඩන්බ්‍රෝක්: වාව් මම කවදාවත් දැනගෙන හිටියේ නැහැ වැරදි පිළිතුරක් ලබා ගැනීම එතරම් පහසුයි කියලා. කෙසේ වෙතත්, යමෙකු නිශ්චිත නොවන සංඛ්‍යා සමඟ වැඩ කරන්නේ නම්, ඕනෑම අගයක් හරියටම නොවන බව යමෙකු හඳුනාගත යුතුය . 265.335සැබවින්ම අදහස් වන්නේ 265.335 += tolerance, ඉවසීම පෙර මෙහෙයුම් සහ ආදාන අගයන් පරාසය මත රඳා පවතින බවය. සත්‍ය, නිශ්චිත වටිනාකම අපි නොදනිමු. අද්දර අගයන්හි, එක්කෝ පිළිතුර විවාදාත්මක ලෙස නිවැරදි ය. අපට හරියටම කිව යුතු නම්, අපි දෙවරක් වැඩ නොකළ යුතුය. මෙම failමෙතන දෙගුණ කිරීමට නැවත පරිවර්තනය තුළ නැත. එහි OP චින්තනයේ දී ඔහුට එන 265.335දේ හරියටම විශ්වාස කළ හැකිය.
මෙවලම් සාදන්නා

191
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);

ඔබට ලැබෙනු ඇත BigDecimal. එය අතරින් වැල, හුදෙක් ඇමතුමක් ලබා ගැනීමට BigDecimalගේ toStringක්රමය, හෝtoPlainString තැනිතලාවක් ආකෘතිය නූල් ජාවා 5+ සඳහා ක්රමයක්.

නියැදි වැඩසටහන:

package trials;
import java.math.BigDecimal;

public class Trials {

    public static void main(String[] args) {
        int yourScale = 10;
        System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
    }

38
ඒක තමයි මම කැමතිම විසඳුම. ඊටත් වඩා කෙටි: BigDecimal.valueOf (doubleVar) .setScale (yourScaleHere, BigDecimal.ROUND_HALF_UP); BigDecimal.valueOf (ද්විත්ව අගය) ඇත්ත වශයෙන්ම ඩබල්.ටොස්ට්‍රිං () හූඩ් යටතේ අමතයි;)
එටියන් නෙවේ

4
හොඳයි. කොන් කැපීම සහ new BigDecimal(doubleVar)පාවෙන ස්ථාන වට කිරීම සම්බන්ධ ගැටළු වලට මුහුණ දිය හැකි පරිදි භාවිතා නොකරන්න
එඩ්

8
සෙබස්තියන්වාන්ඩන්බ්‍රෝක් විසින් ඇස්ටරයිට්ගේ පිළිතුරට අදහස් දැක්වීමේදී වටකුරු ගැටළුව ඇති බව සිත්ගන්නා කරුණකි. double val = 265.335;, BigDecimal.valueOf(val).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();=> 265.34, නමුත් (new BigDecimal(val)).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();=> 265.33.
මෙවලම් සාදන්නා

7
@ToolmakerSteve එයට හේතුව ද්විත්ව සමඟ නව BigDecimal භාවිතා කිරීම ද්විත්ව අගය කෙලින්ම ගෙන එය BigDecimal නිර්මාණය කිරීම සඳහා භාවිතා කිරීමට උත්සාහ කරන අතර BigDecimal.valueOf හෝ ටෝස්ට්‍රිං පෝරමය භාවිතා කරන විට එය පරිවර්තනයට පෙර පළමුවෙන් (වඩාත් නිවැරදි නිරූපණයක්) විග්‍රහ කරයි. .
MetroidFan2002

116

ඔබට ද භාවිතා කළ හැකිය

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

ඔබට 0 පසුපසින් ඇති බව තහවුරු කර ගැනීමට.


25
මම යන ප්රශ්නය වන අරමුණු එකක් "එහි දිය යුතු බවයි විශ්වාස නෑ ඕනෑම අවර zeroes විය".
Lunchbox

7
මෙම ප්‍රශ්නය සඳහා, දෘෂ්ටි කෝණයෙන් ශුන්‍යයන් අවශ්‍ය නොවීය, නමුත් මෙය මට අවශ්‍ය වූයේ හරියටම ය. ඔබ සතුව දශම ස්ථාන 3 ක් සහිත සංඛ්‍යා ලැයිස්තුවක් තිබේ නම්, එය 0 වුවද ඒවා සියල්ලටම එකම ඉලක්කම් තිබිය යුතුය.
ටොම් කින්කයිඩ්

ඔබට සඳහන් කිරීමට අමතක වියRoundingMode.
ඉගෝර්ගනාපොල්ස්කි

1
G ඉගෝර්ගනාපොල්ස්කි පෙරනිමියෙන් Decimal modeභාවිතා කරයිRoundingMode.HALF_EVEN.
EndermanAPM

88

සමහර අය සටහන් කර ඇති පරිදි, නිවැරදි පිළිතුර හෝ භාවිතා කිරීමයි DecimalFormatහෝ BigDecimal. ඉපිලුම් ලක්ෂ්ය නැත ඇති , ඔබ විසින් පළමු ස්ථානයේ ඔවුන් නිශ්චිත සංඛ්යාව හැකි වටය / ලුප්ත නොහැකි නිසා දශම ස්ථාන. ඔබ දශම රේඩියේටරයක වැඩ කළ යුතු අතර, එම පන්ති දෙක කරන්නේ එයයි.

මම පහත දැක්වෙන කේතය මෙම ත්‍රෙඩ් එකේ ඇති සියලුම පිළිතුරු වලට ප්‍රති-නිදසුනක් ලෙස පළ කරමි. ඇත්ත වශයෙන්ම ස්ටැක් ඕවර්ෆ්ලෝ (සහ වෙනත් තැන්වල) පුරාම ගුණ කිරීම නිර්දේශ කර බෙදීමෙන් පසුව බෙදීමෙන් පසුව නිර්දේශ කරමි. 92% කට වඩා වැඩි සංඛ්‍යාවක පහත දැක්වෙන කේතය වැරදි ප්‍රති output ල ලබා දෙන්නේ මන්ද යන්න පැහැදිලි කිරීම මෙම තාක්ෂණයේ උපදේශකයින්ගේ වගකීම වේ.

public class RoundingCounterExample
{

    static float roundOff(float x, int position)
    {
        float a = x;
        double temp = Math.pow(10.0, position);
        a *= temp;
        a = Math.round(a);
        return (a / (float)temp);
    }

    public static void main(String[] args)
    {
        float a = roundOff(0.0009434f,3);
        System.out.println("a="+a+" (a % .001)="+(a % 0.001));
        int count = 0, errors = 0;
        for (double x = 0.0; x < 1; x += 0.0001)
        {
            count++;
            double d = x;
            int scale = 2;
            double factor = Math.pow(10, scale);
            d = Math.round(d * factor) / factor;
            if ((d % 0.01) != 0.0)
            {
                System.out.println(d + " " + (d % 0.01));
                errors++;
            }
        }
        System.out.println(count + " trials " + errors + " errors");
    }
}

මෙම වැඩසටහනේ ප්‍රතිදානය:

10001 trials 9251 errors

සංස්කරණය: සමහර අදහස් මම භාවිතා පරීක්ෂණ පුඩුවක් වූ මාපාංකය කොටසක් redid පහත පිළියමක් BigDecimalහා new MathContext(16)පහත සඳහන් පරිදි මාපාංකය මෙහෙයුම් සඳහා:

public static void main(String[] args)
{
    int count = 0, errors = 0;
    int scale = 2;
    double factor = Math.pow(10, scale);
    MathContext mc = new MathContext(16, RoundingMode.DOWN);
    for (double x = 0.0; x < 1; x += 0.0001)
    {
        count++;
        double d = x;
        d = Math.round(d * factor) / factor;
        BigDecimal bd = new BigDecimal(d, mc);
        bd = bd.remainder(new BigDecimal("0.01"), mc);
        if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
        {
            System.out.println(d + " " + bd);
            errors++;
        }
    }
    System.out.println(count + " trials " + errors + " errors");
}

ප්‍රති ult ලය:

10001 trials 4401 errors

8
උපක්‍රමය නම් ඔබගේ සියලු දෝෂ 9251 හි මුද්‍රිත ප්‍රති result ලය තවමත් නිවැරදි බවය.
ඩිඩියර් එල්

7
IdDidierL එය මා පුදුමයට පත් නොකරයි. මගේ පළමු පරිගණක පා course මාලාව ලෙස 'සංඛ්‍යාත්මක ක්‍රම' කිරීමේ වාසනාව මට තිබූ අතර පාවෙන ස්ථානයට කළ හැකි හා කළ නොහැකි දේ ආරම්භයේදීම හඳුන්වා දෙන ලදී. බොහෝ ක්‍රමලේඛකයින් ඒ ගැන අපැහැදිලි ය.
මාර්ක්විස් ඔෆ් ලෝර්න්

15
ඔබ කරමින් සිටින්නේ පාවෙන බොහෝ දශම අගයන් හරියටම නිරූපණය නොකරන බව ප්‍රතික්ෂේප කිරීමයි. වටකුරු කිරීම ගැටළුවක් ඇති කරන බවක් නොවේ. ඔබ පිළිගන්නා පරිදි, සංඛ්‍යා තවමත් අපේක්ෂිත පරිදි මුද්‍රණය වේ.
පීටර් ලෝරි

8
ඔබගේ පරීක්ෂණය කැඩී ඇත, () පිටතට ගෙන පරීක්ෂණයෙන් 94% ක් අසමත් වේ. ideone.com/1y62CY මුද්‍රණය 100 trials 94 errorsඔබ සමත් විය යුතු පරීක්ෂණයකින් ආරම්භ කළ යුතු අතර, වටකුරු හඳුන්වාදීම මඟින් පරීක්ෂණය බිඳ වැටෙන බව පෙන්වන්න.
පීටර් ලෝරි

6
ප්‍රතික්ෂේප කිරීම, මෙහි ප්‍රතික්ෂේප කිරීම. මෙම පෙළ සඳහා Math.round භාවිතා doubleකිසිදු දෝෂයක් ලෙස ideone.com/BVCHh3
පීටර් Lawrey

83

ඔබ සතුව ඇතැයි සිතමු

double d = 9232.129394d;

ඔයාට පාවිච්චි කරන්න පුළුවන් BigDecimal

BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();

හෝ BigDecimal නොමැතිව

d = Math.round(d*100)/100.0d;

විසඳුම් දෙකම සමඟ d == 9232.13


2
මම හිතන්නේ මෙය ජාවා 1.5 භාවිතා කරන්නන් සඳහා හොඳම විසඳුමයි (සහ පහළ). එක් අදහසක්, HALF_EVEN වටකුරු මාදිලිය භාවිතා නොකරන්න, එයට අමුතු හා ඉරට්ටේ සංඛ්‍යා සඳහා වෙනස් හැසිරීම් ඇති බැවින් (වට 2.5 සිට 2 දක්වා සහ 5.5 සිට 6 දක්වා, උදාහරණයක් ලෙස), මෙය ඔබට අවශ්‍ය නම් මිස.
අයිස්ඩ් ඩැන්ටේ

4
පළමු විසඳුම නිවැරදි ය: දෙවැන්න ක්‍රියා නොකරයි. සාක්ෂි සඳහා මෙහි බලන්න .
මාර්ක්විස් ඔෆ් ලෝර්න්

1
JEJP: පළමු විසඳුම පවා RoundingMode.HALF_UPවැරදියි. එය සමඟ උත්සාහ කරන්න 1.505. නිවැරදි ක්‍රමය භාවිතා කිරීමයි BigDecimal.valueOf(d).
මතියස් බ්‍රවුන්

මතියස් බ්‍රවුන්, විසඳුම හොඳයි, ඒ නිසා ඉහළට 31 යි .. 1.505 දශම 1.50499998 ලෙස පාවෙන ලක්ෂ්‍යයේ දෙගුණයක් ගබඩා කර ඇත. ඔබට 1.505 ගෙන ද්විත්ව සිට දශමයට පරිවර්තනය කිරීමට අවශ්‍ය නම්, ඔබ එය මුලින්ම ඩබල් ටෝස්ට්‍රිං (x) බවට පරිවර්තනය කළ යුතුය. ඉන්පසු එය බිග් ඩෙසිමල් () ට දමන්න, නමුත් එය අතිශයින් මන්දගාමී වන අතර වේගය සඳහා දෙගුණයක් භාවිතා කිරීමේ අරමුණ පරාජය කරයි.
හාමිෂ්

1
බිග් ඩෙසිමල් (එම්එස් 225) සහ මැත්රවුන්ඩ් (එම්එස් 2) මාර්ගය සමඟ 100 කි. : 9232.13 techiesinfo.com
user1114134

60

ඔබට DecimalFormat පන්තිය භාවිතා කළ හැකිය.

double d = 3.76628729;

DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal =  Double.valueOf(newFormat.format(d));

Double.valueOf()තෝරා ගැනීමට හේතුවක් Double.parseDouble()තිබේද? මෙම valueOf()ක්රමය නැවත Doubleඇති අතර, වස්තුව parseDouble()වූ ආපසු doubleප්රාථමික. වත්මන් කේතය ලියා ඇති ආකාරයත් සමඟම, ඔබේ twoDoubleවිචල්‍යය අපේක්ෂා කරන ප්‍රාථමිකයට වාත්තු කිරීම සඳහා නැවත ස්වයංක්‍රීයව-බොක්සිං යෙදීම , අතිරේක බයිට් කේත මෙහෙයුමක්. මම ඒ parseDouble()වෙනුවට භාවිතා කිරීමට පිළිතුර වෙනස් කරමි .
ecbrodie

Double.parseDouble()Stringආදානය අවශ්‍යයි .
රයිඩ්

38

රියල්හි ජාවා මෙම විසඳුම පළ කරන්නේ කෙසේද , එය ජාවා 1.6 ට පෙර අනුවාද සඳහාද අනුකූල වේ.

BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();

33
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;

2
ඔව්, ධනාත්මක සංඛ්‍යා සඳහා math.round කරන්නේ හරියටම මෙයයි, නමුත් ඔබ මෙය negative ණ සංඛ්‍යා සමඟ උත්සාහ කර තිබේද? negative ණ සංඛ්‍යා සම්බන්ධව ආවරණය කිරීම සඳහා මිනිසුන් අනෙක් විසඳුම්වල math.round භාවිතා කරයි.
හාමිෂ්

සටහන: Math.floor(x + 0.5)සහMath.round(x)
පීටර් ලෝරි

30

Il මිල්හවුස්: වටකුරු කිරීම සඳහා දශම ආකෘතිය විශිෂ්ටයි:

ඔබට ද භාවිතා කළ හැකිය

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

ඔබට 0 පසුපසින් ඇති බව තහවුරු කර ගැනීමට.

දෘශ්‍යමය වශයෙන් පමණක් නොව, සැකසීමේදී ද සත්‍ය සංඛ්‍යාත්මක, වටකුරු යාන්ත්‍රණයක් සැපයීමට මෙම ක්‍රමය ඉතා හොඳ බව මම එකතු කරමි.

උපකල්පිත: ඔබ GUI වැඩසටහනකට වටකුරු යාන්ත්‍රණයක් ක්‍රියාත්මක කළ යුතුය. ප්‍රති output ල ප්‍රතිදානයක නිරවද්‍යතාවය / නිරවද්‍යතාවය වෙනස් කිරීම සඳහා භාරකාර ආකෘතිය වෙනස් කරන්න (එනම් වරහන් තුළ). ඉතින් එතකොට:

DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);

ප්‍රතිදානය ලෙස නැවත පැමිණේ: 0.912385

DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);

ප්‍රතිදානය ලෙස නැවත පැමිණේ: 0.91239

DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);

ප්‍රතිදානය ලෙස නැවත පැමිණේ: 0.9124

[සංස්කරණය කරන්න: කැරට් ආකෘතියද එසේ නම් ("# 0. ###########") සහ ඔබ දශමයක් ඇතුළත් කරන්න, උදා. උදා: ශුන්‍ය පසුපස ලුහුබඳිමින්) නැවත පැමිණෙනු ඇත: 3.1415926.. ඔබ එසේ නැඹුරු නම්. සමහර දේව්ගේ රුචිකත්වයට එය ටිකක් වාචික බව ඇත්තයි - නමුත් හේයි, එය සැකසීමේදී අඩු මතක සටහනක් ඇති අතර එය ක්‍රියාත්මක කිරීම ඉතා පහසුය.]

එබැවින් අත්‍යවශ්‍යයෙන්ම ඩෙසිමල් ෆෝමැට්හි සුන්දරත්වය නම් එය එකවරම නූල් පෙනුම හසුරුවයි - එසේම වටකුරු නිරවද්‍යතා කට්ටලයේ මට්ටමයි. Ergo: එක් කේත ක්‍රියාත්මක කිරීමේ මිල සඳහා ඔබට ප්‍රතිලාභ දෙකක් ලැබේ. ;)


2
ඔබ ඇත්තටම (හා පමණක් ප්රතිදානය සඳහා) ගණනය කිරීම සඳහා දශම සංඛ්යා අවශ්ය නම්, ද්විමය-පදනම් ඉපිලුම් ලක්ෂ්ය ආකෘතිය භාවිතා නොකරන මෙන් double. BigDecimal හෝ වෙනත් දශම පදනම් කරගත් ආකෘතියක් භාවිතා කරන්න.
Paŭlo Ebermann

20

ප්‍රති string ලය String ලෙස ඔබට අවශ්‍ය නම් ඔබට භාවිතා කළ හැකි දේ පිළිබඳ සාරාංශයක් මෙන්න:

  1. DecimalFormat # setRoundingMode () :

    DecimalFormat df = new DecimalFormat("#.#####");
    df.setRoundingMode(RoundingMode.HALF_UP);
    String str1 = df.format(0.912385)); // 0.91239
  2. BigDecimal # setScale ()

    String str2 = new BigDecimal(0.912385)
        .setScale(5, BigDecimal.ROUND_HALF_UP)
        .toString();

මෙහි ප්‍රති .ලයක් doubleලෙස ඔබට අවශ්‍ය නම් භාවිතා කළ හැකි පුස්තකාල මොනවාද යන්න පිළිබඳ යෝජනාවකි . දෙවරක් ඔබට අවශ්‍ය දේ හරියටම නිරූපණය කිරීමට නොහැකි විය හැකි බැවින් මම එය නූල් පරිවර්තනය සඳහා නිර්දේශ නොකරමි (උදා: මෙහි බලන්න ):

  1. අපාචේ කොමන්ස් ගණිතයෙන් නිරවද්‍යතාවය

    double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
  2. කෝල්ට් වෙතින් කාර්යයන්

    double rounded = Functions.round(0.00001).apply(0.912385)
  3. වෙකා වෙතින් උපයෝගීතා

    double rounded = Utils.roundDouble(0.912385, 5)

18

ඔබට පහත උපයෝගීතා ක්‍රමය භාවිතා කළ හැකිය-

public static double round(double valueToRound, int numberOfDecimalPlaces)
{
    double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
    double interestedInZeroDPs = valueToRound * multipicationFactor;
    return Math.round(interestedInZeroDPs) / multipicationFactor;
}

arimariolpantunes: එය අසාර්ථක වනු ඇත. මෙය උත්සාහ කරන්න: round(1.005,2);හෝround(0.50594724957626620092, 20);
මතියස් බ්‍රවුන්

එය වැඩ කරනවා. නමුත් අවිධිමත් ලෙස පාවෙන සහ යුගල වශයෙන් දළ වශයෙන් දැක්වේ. ඔබගේ පළමු උදාහරණය සලකා බලමු. ඔබ උනන්දුවක් දක්වන ඉන්සීරෝඩීපී වල ප්‍රතිදානය Math.round ට පෙර මුද්‍රණය කරන්නේ නම් එය 100.49999999999999 මුද්‍රණය කරනු ඇත. ගණිතය 100 වැනි වටය වැනි නිරවද්‍යතාවය ඔබට අහිමි විය. ස්වභාවය හෝ පාවෙන හා දෙගුණ වීම නිසා එය නිසි ලෙස ක්‍රියාත්මක නොවන විට දේශසීමා අවස්ථා තිබේ (වැඩි විස්තර මෙහි en.wikipedia.org/wiki/Floating_point#Accuracy_problems )
mariolpantunes

දෙගුණයක් උපවාසයකි! දශම මන්දගාමී වේ. පරිගණක ඔවුන්ගේ චින්තනය දශම අංකනයෙන් සැකසීමට කරදර වන්නේ නැත. පාවෙන ස්ථානය දෙවරක් වේගයෙන් තබා ගැනීම සඳහා ඔබ යම් දශම නිරවද්‍යතාවයක් අත්හැරිය යුතුය.
හාමිෂ්

@ හමීෂ් ප්‍රශ්නය නිරවද්‍යතාව ගැන මිස වේගය ගැන නොවේ.
ලෝර්න් හි මාක්විස්



7

මෙය උත්සාහ කරන්න: org.apache.commons.math3.util.Precision.round (ද්විත්ව x, int පරිමාණය)

බලන්න: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html

අපාචේ කොමන්ස් ගණිත පුස්තකාල මුල් පිටුව: http://commons.apache.org/proper/commons-math/index.html

මෙම ක්‍රමයේ අභ්‍යන්තර ක්‍රියාත්මක කිරීම:

public static double round(double x, int scale) {
    return round(x, scale, BigDecimal.ROUND_HALF_UP);
}

public static double round(double x, int scale, int roundingMethod) {
    try {
        return (new BigDecimal
               (Double.toString(x))
               .setScale(scale, roundingMethod))
               .doubleValue();
    } catch (NumberFormatException ex) {
        if (Double.isInfinite(x)) {
            return x;
        } else {
            return Double.NaN;
        }
    }
}

7

මෙම තේමාවට සම්පූර්ණ පිළිතුරක් මට හමු නොවූ හෙයින්, මෙය නිසි ලෙස හැසිරවිය යුතු පන්තියක් මම එකට තබා ඇත.

  • හැඩතල ගැන්වීම : නිශ්චිත දශම ස්ථාන සංඛ්‍යාවක් සමඟ ද්විත්ව සිට නූල් පහසුවෙන් සංයුති කරන්න
  • විග්‍රහ කිරීම : ආකෘතිගත කළ අගය දෙගුණයක් දක්වා විග්‍රහ කරන්න
  • පෙදෙසි : ආකෘතිය හා parse පෙරනිමි ප්රාදේශිකය භාවිතා
  • On ාතීය අංකනය : යම් සීමාවකට පසු on ාතීය අංකනය භාවිතා කිරීම ආරම්භ කරන්න

භාවිතය ඉතා සරල ය :

(මෙම උදාහරණය සඳහා මම අභිරුචි පෙදෙසක් භාවිතා කරමි)

public static final int DECIMAL_PLACES = 2;

NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);

String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"

double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345

මෙන්න පන්තිය :

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;

public class NumberFormatter {

    private static final String SYMBOL_INFINITE           = "\u221e";
    private static final char   SYMBOL_MINUS              = '-';
    private static final char   SYMBOL_ZERO               = '0';
    private static final int    DECIMAL_LEADING_GROUPS    = 10;
    private static final int    EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
    private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation

    private DecimalFormat decimalFormat;
    private DecimalFormat decimalFormatLong;
    private DecimalFormat exponentialFormat;

    private char groupSeparator;

    public NumberFormatter(int decimalPlaces) {
        configureDecimalPlaces(decimalPlaces);
    }

    public void configureDecimalPlaces(int decimalPlaces) {
        if (decimalPlaces <= 0) {
            throw new IllegalArgumentException("Invalid decimal places");
        }

        DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
        separators.setMinusSign(SYMBOL_MINUS);
        separators.setZeroDigit(SYMBOL_ZERO);

        groupSeparator = separators.getGroupingSeparator();

        StringBuilder decimal = new StringBuilder();
        StringBuilder exponential = new StringBuilder("0.");

        for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
            decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
        }

        for (int i = 0; i < decimalPlaces; i++) {
            decimal.append("#");
            exponential.append("0");
        }

        exponential.append("E0");

        decimalFormat = new DecimalFormat(decimal.toString(), separators);
        decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
        exponentialFormat = new DecimalFormat(exponential.toString(), separators);

        decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
        decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
        exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
    }

    public String format(double value) {
        String result;
        if (Double.isNaN(value)) {
            result = "";
        } else if (Double.isInfinite(value)) {
            result = String.valueOf(SYMBOL_INFINITE);
        } else {
            double absValue = Math.abs(value);
            if (absValue >= 1) {
                if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
                    value = Math.floor(value);
                    result = exponentialFormat.format(value);
                } else {
                    result = decimalFormat.format(value);
                }
            } else if (absValue < 1 && absValue > 0) {
                if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
                    result = decimalFormat.format(value);
                    if (result.equalsIgnoreCase("0")) {
                        result = decimalFormatLong.format(value);
                    }
                } else {
                    result = exponentialFormat.format(value);
                }
            } else {
                result = "0";
            }
        }
        return result;
    }

    public String formatWithoutGroupSeparators(double value) {
        return removeGroupSeparators(format(value));
    }

    public double parse(String value, double defValue) {
        try {
            return decimalFormat.parse(value).doubleValue();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return defValue;
    }

    private String removeGroupSeparators(String number) {
        return number.replace(String.valueOf(groupSeparator), "");
    }

}

7

ගණනය කිරීම සඳහා ඔබට සැබවින්ම දශම සංඛ්‍යා අවශ්‍ය නම් (සහ ප්‍රතිදානය සඳහා පමණක් නොවේ), ද්විත්ව වැනි ද්විමය පාදක පාවෙන ලක්ෂ්‍ය ආකෘතියක් භාවිතා නොකරන්න.

Use BigDecimal or any other decimal-based format.

මම ගණනය කිරීම් සඳහා BigDecimal භාවිතා කරමි, නමුත් මතක තබා ගන්න එය ඔබ සමඟ ගනුදෙනු කරන සංඛ්‍යා ප්‍රමාණය මත රඳා පවතී. මගේ බොහෝ ක්‍රියාත්මක කිරීම් වලදී, ද්විත්ව හෝ පූර්ණ සංඛ්‍යා සිට දිගු දක්වා විග්‍රහ කිරීම ඉතා විශාල සංඛ්‍යා ගණනය කිරීම් සඳහා ප්‍රමාණවත් බව මට පෙනේ.

ඇත්ත වශයෙන්ම, ################# තරම් විශාල සංඛ්‍යා සඳහා GUI එකක නිවැරදි නිරූපණයන් (හෙක්ස් ප්‍රති results ලවලට වෙනස්ව) ලබා ගැනීම සඳහා මම මෑතකදී විග්‍රහ කර ඇත. ############### අක්ෂර (උදාහරණයක් ලෙස).


6

මෙය සාක්ෂාත් කර ගැනීම සඳහා අපට මෙම ආකෘතිය භාවිතා කළ හැකිය:

 DecimalFormat df = new DecimalFormat("#.00");
 String resultado = df.format(valor)

හෝ:

DecimalFormat df = new DecimalFormat("0.00"); :

සෑම විටම දශම දෙකක් ලබා ගැනීමට මෙම ක්‍රමය භාවිතා කරන්න:

   private static String getTwoDecimals(double value){
      DecimalFormat df = new DecimalFormat("0.00"); 
      return df.format(value);
    }

මෙම අගයන් නිර්වචනය කිරීම:

91.32
5.22
11.5
1.2
2.6

අපට මෙම ප්‍රති results ල ලබා ගත හැකි ක්‍රමය භාවිතා කරමින්:

91.32
5.22
11.50
1.20
2.60

අන්තර්ජාලය හරහා නිරූපණය.


5

යමෙකුට තවමත් මේ සඳහා උදව් අවශ්‍ය නම්. මෙම විසඳුම මට හොඳින් ක්රියා කරයි.

private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals,  BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();

}

String අපේක්ෂිත ප්‍රතිදානය සමඟ a ලබා දෙයි.


කරුණාකර අදහස් දැක්වීමේදී පහත් කොට සැලකීමට ඔබේ හේතුව ඇතුළත් කරන්න, එසේ නොමැති නම් එය බිය ගැන්වීම ලෙස අපි හඳුන්වමු.
ආශර්. M. O

4

භාවිතා කිරීමට තෝරාගත් පිළිතුර සමඟ මම එකඟ වෙමි DecimalFormat--- හෝ විකල්පයක් ලෙසBigDecimal .

කරුණාකර පළමුව යාවත්කාලීන කිරීම කියවන්න !

ඔබ නම් කෙසේ වෙතත් නැහැ ද්විත්ව අගය අවට සහ ලබා ගැනීමට අවශ්ය doubleවටිනාකම නිසා, ඔබ භාවිතා කළ හැකිය org.apache.commons.math3.util.Precision.round(..)ඉහත සඳහන් පරිදි. ක්‍රියාත්මක කිරීම භාවිතා BigDecimalකිරීම මන්දගාමී වන අතර කුණු කසළ නිර්මාණය කරයි.

DoubleRounderදශම 4j පුස්තකාලයේ ඇති උපයෝගීතාවයෙන් සමාන නමුත් වේගවත් හා කසළ රහිත ක්‍රමයක් සපයනු ලැබේ :

 double a = DoubleRounder.round(2.0/3.0, 3);
 double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
 double c = DoubleRounder.round(1000.0d, 17);
 double d = DoubleRounder.round(90080070060.1d, 9);
 System.out.println(a);
 System.out.println(b);
 System.out.println(c);
 System.out.println(d);

ප්‍රතිදානය කරයි

 0.667
 0.666
 1000.0
 9.00800700601E10

Https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility බලන්න

වියාචනය: මම decimal4j ව්‍යාපෘතියට සම්බන්ධ වෙමි.

යාවත්කාලීන කිරීම: @iaforek පෙන්වා දුන් පරිදි ඩබල් රවුන්ඩර් සමහර විට ප්‍රතිවිරුද්ධ ප්‍රති .ල ලබා දෙයි. හේතුව එය ගණිතමය වශයෙන් නිවැරදි වටකුරු කිරීමකි. උදාහරණයක් වශයෙන්DoubleRounder.round(256.025d, 2) ලෙස 256.025d ලෙස නිරූපණය කෙරෙන 256.025d ලෙස දැක්වෙන ද්විත්ව අගය 256.025 තාර්කික අගයට වඩා තරමක් කුඩා වන අතර එම නිසා එය වටකුරු වනු ඇත.

සටහන්:

  • මෙම හැසිරීම BigDecimal(double)ඉදිකිරීම්කරුගේ හැසිරීමට බෙහෙවින් සමාන ය (නමුත් valueOf(double)නූල් සාදන්නා භාවිතා නොකරන ).
  • පළමුවෙන්ම ද්විත්ව වටකුරු පියවරකින් ඉහළ නිරවද්‍යතාවයකින් ගැටලුව මඟහරවා ගත හැකි නමුත් එය සංකීර්ණ වන අතර මම මෙහි විස්තර වෙත නොයමි

එම හේතු සහ මෙම ලිපියේ ඉහත සඳහන් සියල්ල සඳහා මට ඩබල් රවුන්ඩර් භාවිතා කිරීමට නිර්දේශ කළ නොහැක .


ඔබේ විසඳුම අනෙක් ඒවාට සාපේක්ෂව කොතරම් කාර්යක්ෂමද යන්න පෙන්වන ප්‍රමිතික ඔබ සතුව තිබේද?
iaforek

මම එය වෙනත් විසඳුම් සමඟ සංසන්දනය කර නැති නමුත් ප්‍රභව කේතයේ jmh මිණුම් ලකුණක් ඇත: github.com/tools4j/decimal4j/blob/master/src/jmh/java/org/… මම මිණුම් ලකුණ VM මත ධාවනය කළෙමි , ප්‍රති results ල
marco

1
පහත දැක්වෙන අවස්ථා සඳහා DoubleRounder අසමත් වේ: DoubleRounder.round (256.025d, 2) - අපේක්ෂිත: 256.03, තථ්‍ය: 256.02 හෝ DoubleRounder.round සඳහා (260.775d, 2) - අපේක්ෂිත: 260.78, සත්‍ය: 260.77.
iaforek

foreiaforek: මෙය නිවැරදි ය, මන්ද ඩබල් රවුන්ඩර් ගණිතමය වශයෙන් නිවැරදි වටකුරු කිරීම සිදු කරයි. කෙසේ වෙතත් මෙය තරමක් ප්‍රතිවිරුද්ධ බව මම පිළිගනිමි. එබැවින් මගේ පිළිතුර ඒ අනුව යාවත්කාලීන කරමි.
මාර්කෝ

3

පහත දැක්වෙන කේත ස්නිපටයේ ඉලක්කම් n පෙන්වන ආකාරය පෙන්වයි. උපක්‍රමය නම් විචල්ය pp 1 ලෙස සකසා n ශුන්‍යයන් අනුගමනය කිරීමයි. පහත උදාහරණයේ, විචල්ය pp අගයට ශුන්‍ය 5 ක් ඇත, එබැවින් ඉලක්කම් 5 ක් දර්ශනය වේ.

double pp = 10000;

double myVal = 22.268699999999967;
String needVal = "22.2687";

double i = (5.0/pp);

String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();

3

ඔබ DecimalFormatපරිවර්තනය doubleකිරීමට භාවිතා කරන්නේ නම් String, එය ඉතා සරල ය:

DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);

double num = 1.234567;
return formatter.format(num);

RoundingModeඔබට අවශ්‍ය හැසිරීම අනුව තෝරා ගැනීමට enum අගයන් කිහිපයක් තිබේ .


3

මම මෙහි පැමිණියේ අංකයක් වට කරන්නේ කෙසේද යන්න පිළිබඳ සරල පිළිතුරක් අවශ්‍යවය. එය සැපයීම සඳහා මෙය අතිරේක පිළිතුරකි.

ජාවා හි අංකයක් වට කරන්නේ කෙසේද

වඩාත් පොදු අවස්ථාව වන්නේ භාවිතා කිරීමයි Math.round().

Math.round(3.7) // 4

අංක ආසන්නතම මුළු අංකයට වට කර ඇත. ඒ .5වටිනාකම රැස්වූ අතර වේ. ඔබට ඊට වඩා වෙනස් වටකුරු හැසිරීමක් අවශ්‍ය නම්, ඔබට අනෙක් ගණිතය භාවිතා කළ හැකිය ශ්‍රිතයක් . පහත සංසන්දනය බලන්න.

වටය

ඉහත සඳහන් කළ පරිදි, මෙය ආසන්නතම සම්පූර්ණ අංකයට වට වේ. .5දශම වටය. මෙම ක්‍රමය මඟින් නැවත ලබා දෙනු ලැබේ int.

Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4

Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4

සිවිලිම

ඕනෑම දශම අගයක් ඊළඟ නිඛිලය දක්වා වට කර ඇත. එය සිවිලිමට යයි . මෙම ක්‍රමය මඟින් a double.

Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0

Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0

මහල

ඕනෑම දශම අගයක් ඊළඟ නිඛිලය දක්වා වට කර ඇත. මෙම ක්‍රමය මඟින් a double.

Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0

Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0

රින්ට්

මෙය ආසන්න දශකයට ආසන්නව ඇති දශම අගයන්හි වටයට සමාන වේ. කෙසේ වෙතත්, මෙන් නොව round, .5අගයන් ඒකාකාරයට සමාන වේ. මෙම ක්‍රමය මඟින් a double.

Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***

Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***

1
ඔබ විසඳන්නේ නිශ්චිත වටය දශම 0 දක්වා පමණි. මුල් ප්‍රශ්නය වඩාත් ජනක ය.
lukas84

3

ඔබ භාවිතා කරන්නේ අවම JDK සහිත තාක්ෂණයක් නම්. ජාවා ලිබ්ස් නැති ක්‍රමයක් මෙන්න:

double scale = 100000;    
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;

MyVal 1 ට නොඅඩු හා පරිමාණ අගයෙන් ඔබ්බට දශමයෙන් පසු ශුන්‍ය සමඟ මෙය අසමත් වේ. ඔබට myVal = 9.00000000912385 ඇති බව පවසන්න; ඉහත 9.0 නැවත ලබා දෙනු ඇත. මම හිතන්නේ අපි myVal හි සෑම අවස්ථාවකම ක්‍රියාත්මක වන විසඳුමක් ලබා දිය යුතුයි. ඔබ සඳහන් කළ අගය සඳහා විශේෂයෙන් නොවේ.
tavalendo

example user102859 ඔබේ උදාහරණයේ 9.0 යනු නිවැරදි ප්‍රති .ලයයි. මෙය අසාර්ථක වන්නේ කෙසේදැයි මට තේරෙන්නේ නැත.
ක්‍රේගෝ

2

නිමැවුම් සඳහා හොඳම ක්‍රමය DecimalFormat, නමුත් මම එයට කැමති නැත. මම සෑම විටම මෙය කරන්නේ, එය ද්විත්ව අගය ලබා දෙන බැවිනි. එබැවින් මට එය ප්‍රතිදානයට වඩා භාවිතා කළ හැකිය.

Math.round(selfEvaluate*100000d.0)/100000d.0;

හෝ

Math.round(selfEvaluate*100000d.0)*0.00000d1;

ඔබට විශාල දශම ස්ථාන වටිනාකමක් අවශ්‍ය නම්, ඒ වෙනුවට ඔබට BigDecimal භාවිතා කළ හැකිය. කෙසේ වෙත් .0වැදගත් වේ. එය නොමැතිව 0.33333d5 ආපසු හැරවීම 0.33333 වන අතර ඉලක්කම් 9 ක් පමණි. නොමැතිව දෙවන ශ්‍රිතයට .00.30000 ප්‍රතිලාභ 0.30000000000000004 සමඟ ගැටළු ඇත.


2

මෙන්න මගේ පිළිතුර:

double num = 4.898979485566356;
DecimalFormat df = new DecimalFormat("#.##");      
time = Double.valueOf(df.format(num));

System.out.println(num); // 4.89

1

එබැවින් බොහෝ පිළිතුරු කියවීමෙන් පසුව, ඒවායින් බොහොමයක් නිරවද්‍ය නොවන බව මට වැටහුණි, ඇත්ත වශයෙන්ම භාවිතා BigDecimalකිරීම හොඳම තේරීම සේ පෙනේ, නමුත් RoundingModeක්‍රියා කරන ආකාරය ඔබට වැටහෙන්නේ නැත්නම් , ඔබට අනිවාර්යයෙන්ම නිරවද්‍යතාවය නැති වනු ඇත. ව්යාපෘතියක විශාල සංඛ්යා සමඟ වැඩ කරන විට මම මෙය හදුනාගත් අතර එය වටකුරු සංඛ්යා ඇති අනෙක් අයට උපකාර කළ හැකි යැයි සිතුවෙමි. උදාහරණයක් වශයෙන්.

BigDecimal bd = new BigDecimal("1363.2749");
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println(bd.doubleValue());

ඔබ 1363.28ප්‍රතිදානයක් ලෙස ලබා ගැනීමට අපේක්ෂා කරනු ඇත, නමුත් 1363.27ඔබ කරන්නේ කුමක්දැයි ඔබ නොදන්නේ නම්, ඔබ බලාපොරොත්තු නොවනු RoundingModeඇත. එබැවින් ඔරකල් ලියකියවිලි දෙස බැලීමේදී ඔබට පහත විස්තරය සොයාගත හැකිය RoundingMode.HALF_UP.

අසල්වැසියන් දෙදෙනාම සමතුලිත නොවන්නේ නම්, "ළඟම අසල්වැසියා" දෙසට රවුම් කිරීමේ මාදිලිය.

එබැවින් මෙය දැන ගැනීමෙන් අපට වැටහී ගියේ අපට ළඟම ඇති අසල්වැසියා දෙසට ගමන් කිරීමට අවශ්‍ය නම් මිස අපට නිශ්චිත වටයක් නොලැබෙන බවයි . එබැවින්, ප්‍රමාණවත් වටයක් සිදු කිරීම සඳහා, අපට දශමයේ සිට n-1අපේක්ෂිත දශම සංඛ්‍යා දෙසට ලූප අවශ්‍ය වේ . උදාහරණයක් වශයෙන්.

private double round(double value, int places) throws IllegalArgumentException {

    if (places < 0) throw new IllegalArgumentException();

    // Cast the number to a String and then separate the decimals.
    String stringValue = Double.toString(value);
    String decimals = stringValue.split("\\.")[1];

    // Round all the way to the desired number.
    BigDecimal bd = new BigDecimal(stringValue);
    for (int i = decimals.length()-1; i >= places; i--) {
        bd = bd.setScale(i, RoundingMode.HALF_UP);
    }

    return bd.doubleValue();
}

මෙය අපට අපේක්ෂිත ප්‍රතිදානය ලබා දෙනු ඇත, එය වනු ඇත 1363.28.


1

මම ජාවා 8 හි මෙන් බෙලෝ භාවිතා කර ඇත. එය මට වැඩ කරයි

    double amount = 1000.431;        
    NumberFormat formatter = new DecimalFormat("##.00");
    String output = formatter.format(amount);
    System.out.println("output = " + output);

ප්‍රතිදානය:

output = 1000.43

0

එහිදී ඔබට අවශ්‍ය dp = දශම ස්ථානය, සහ අගය දෙගුණයකි.

    double p = Math.pow(10d, dp);

    double result = Math.round(value * p)/p;

1
සහ 1.0සඳහා නිෂ්පාදනය කරයි . වෙනුවට මෙය භාවිතා කරන්න . value = 1.005dp = 2
මතියස් බ්‍රවුන්

ඒක හරි මැට්, ඔබේ උදාහරණය වලංගු නැහැ. 1.005 කෙසේ වෙතත් පාවෙන ලක්ෂ්‍යයෙන් දෙවරක් නිරූපණය කළ නොහැකි බැවිනි. එය සැබවින්ම 1.005 ට වඩා ඉහළින් හෝ පහළින් ගබඩා කළ යුතුය, එනම් ඔබ සම්පාදනය කරන විට එය දෙගුණයක් ලෙස ගබඩා කර ඇත: 1.0049998 (පා comp කයින් විශ්වාස කරන පරිදි එය ඔබේ සම්පාදිත කේතයේ දශම ලෙස ගබඩා නොවේ) ඉලක්කය නිවැරදි ය, ඔහු වටිනාකම් පාවෙන ලක්ෂ්‍යයක් ලෙස ගබඩා කරයි දෙගුණයක්, ඔබ වැනි වාචික අවස්ථා කෙසේ වෙතත් වැදගත් නොවේ. එය එසේ නම්, ඔබ 3dp භාවිතා කර එය දශමයට පරිවර්තනය කර, ඔබ පළ කළ සබැඳිය මෙන් දශම වටයේ ශ්‍රිතයක් කරයි.
හාමිෂ්

1
වටිනාකම දශම ලෙස සම්පාදනය කර ඇති ඕනෑම දෙයක් මතියස් පා readers කයන්ට විශ්වාස කරනු ඇතැයි මම නොදනිමි. අන් අයගේ කටට වචන දමන්න එපා.
ලෝර්න් හි මාක්විස්

0

String.format () සහ DecimalFormat විසින් පෙරනිමි පෙදෙසි භාවිතා කරමින් නූල් නිපදවන බව මතක තබා ගන්න. එබැවින් ඔවුන් පූර්ණ සංඛ්‍යා හා දශම කොටස් අතර බෙදුම්කරුවෙකු ලෙස තිත් හෝ කොමාව සමඟ ආකෘතිගත අංකය ලිවිය හැකිය. වටකුරු නූල් ඔබට අවශ්‍ය ආකෘතියෙන් ඇති බව තහවුරු කර ගැනීමට java.text.NumberFormat භාවිතා කරන්න:

  Locale locale = Locale.ENGLISH;
  NumberFormat nf = NumberFormat.getNumberInstance(locale);
  // for trailing zeros:
  nf.setMinimumFractionDigits(2);
  // round to 2 digits:
  nf.setMaximumFractionDigits(2);

  System.out.println(nf.format(.99));
  System.out.println(nf.format(123.567));
  System.out.println(nf.format(123.0));

ඉංග්‍රීසි භාෂාවෙන් මුද්‍රණය කරනු ඇත (ඔබගේ ස්ථානය කුමක් වුවත්): 0.99 123.57 123.00

උදාහරණය ෆැරෙන්ඩා වෙතින් ලබාගෙන ඇත - ද්විත්ව නූල් නිවැරදිව පරිවර්තනය කරන්නේ කෙසේද .

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.