Pertanyaan Mengapa tidak menggunakan Double atau Float untuk mewakili mata uang?


Saya selalu diberitahu tak pernah untuk mewakili uang dengan double atau float jenis, dan kali ini saya mengajukan pertanyaan kepada Anda: mengapa?

Saya yakin ada alasan yang sangat bagus, saya hanya tidak tahu apa itu.


763
2017-09-16 19:23


asal


Jawaban:


Karena float dan doubles tidak dapat secara akurat mewakili basis 10 kelipatan yang kita gunakan untuk uang. Masalah ini tidak hanya untuk Java, itu untuk bahasa pemrograman yang menggunakan basis 2 tipe floating-point.

Di basis 10, Anda dapat menulis 10,25 sebagai 1025 * 10-2 (kali integer daya 10). Nomor floating-point IEEE-754 berbeda, tetapi cara yang sangat sederhana untuk memikirkannya adalah dengan mengalikan dengan kekuatan dua gantinya. Misalnya, Anda bisa melihat pada 164 * 2-4 (kali integer daya dua), yang juga sama dengan 10,25. Itu bukan bagaimana angka diwakili dalam memori, tetapi implikasi matematika adalah sama.

Bahkan dalam basis 10, notasi ini tidak dapat secara akurat mewakili sebagian besar pecahan sederhana. Misalnya, Anda tidak dapat mewakili 1/3: representasi desimal berulang (0,3333 ...), jadi tidak ada bilangan bulat terbatas yang dapat Anda kalikan dengan kekuatan 10 untuk mendapatkan 1/3. Anda bisa menyelesaikan pada urutan panjang 3 dan eksponen kecil, seperti 333333333 * 10-10, tetapi tidak akurat: jika Anda mengalikannya dengan 3, Anda tidak akan mendapatkan 1.

Namun, untuk tujuan penghitungan uang, setidaknya untuk negara-negara yang uangnya dihargai dalam urutan besarnya dolar AS, biasanya yang Anda butuhkan adalah dapat menyimpan kelipatan 10-2, jadi tidak masalah 1/3 tidak bisa diwakili.

Masalah dengan pelampung dan ganda adalah bahwa Sebagian besar jumlah uang seperti tidak memiliki representasi yang tepat sebagai kali integer kekuatan 2. Bahkan, kelipatan hanya 0,01 antara 0 dan 1 (yang signifikan ketika berhadapan dengan uang karena mereka sen integer) yang dapat diwakili tepat sebagai angka floating-point biner IEEE-754 adalah 0, 0,25, 0,5, 0,75 dan 1. Yang lainnya tidak aktif dalam jumlah kecil. Sebagai analogi contoh 0.333333, jika Anda mengambil nilai floating-point untuk 0,1 dan Anda mengalikannya dengan 10, Anda tidak akan mendapatkan 1.

Mewakili uang sebagai double atau float mungkin akan terlihat bagus pada awalnya karena perangkat lunak membulatkan kesalahan kecil, tetapi ketika Anda melakukan lebih banyak penambahan, pengurangan, perkalian dan pembagian pada nomor yang tidak sama, kesalahan akan bertambah dan Anda akan berakhir dengan nilai yang tampak tidak akurat. Ini membuat pelampung dan ganda tidak memadai untuk berurusan dengan uang, di mana akurasi sempurna untuk kelipatan kekuatan basis 10 diperlukan.

Solusi yang bekerja di hampir semua bahasa adalah dengan menggunakan bilangan bulat sebagai gantinya, dan menghitung sen. Misalnya, 1025 akan menjadi $ 10,25. Beberapa bahasa juga memiliki tipe bawaan untuk menangani uang. Antara lain, Java memiliki BigDecimal kelas, dan C # memiliki decimal mengetik.


788
2017-09-16 19:26



Dari Bloch, J., Effective Java, 2nd ed, Item 48:

Itu float dan double jenisnya   sangat tidak cocok untuk moneter   perhitungan karena tidak mungkin   untuk mewakili 0,1 (atau lainnya   kekuatan negatif sepuluh) sebagai float atau    double persis.

Misalnya, Anda memiliki $ 1,03   dan Anda menghabiskan 42c. Berapa banyak uang   kamu telah pergi?

System.out.println(1.03 - .42);

mencetak 0.6100000000000001.

Cara yang tepat untuk mengatasi masalah ini adalah   menggunakan BigDecimal, int atau long   untuk perhitungan moneter.


270
2017-09-16 19:52



Ini bukan masalah akurasi, juga bukan masalah presisi. Ini adalah masalah memenuhi harapan manusia yang menggunakan basis 10 untuk perhitungan, bukan basis 2. Sebagai contoh, menggunakan ganda untuk perhitungan keuangan tidak menghasilkan jawaban yang "salah" dalam arti matematika, tetapi dapat menghasilkan jawaban yang bukan apa yang diharapkan dalam pengertian finansial.

Bahkan jika Anda membulatkan hasil Anda pada menit terakhir sebelum keluar, Anda masih bisa sesekali mendapatkan hasil menggunakan ganda yang tidak sesuai dengan harapan.

Menggunakan kalkulator, atau menghitung hasil dengan tangan, 1,40 * 165 = 231 tepatnya. Namun, secara internal menggunakan ganda, pada lingkungan kompiler / sistem operasi saya, itu disimpan sebagai bilangan biner mendekati 230,99999 ... jadi jika Anda memotong bilangan, Anda mendapatkan 230 bukan 231. Anda mungkin beralasan bahwa pembulatan bukannya pemotongan akan telah memberikan hasil yang diinginkan dari 231. Itu benar, tetapi pembulatan selalu melibatkan pemotongan. Apapun teknik pembulatan yang Anda gunakan, masih ada kondisi batas seperti ini yang akan membulatkan ketika Anda mengharapkannya untuk mengumpulkan. Mereka cukup langka sehingga sering tidak akan ditemukan melalui pengujian atau observasi biasa. Anda mungkin harus menulis beberapa kode untuk mencari contoh yang mengilustrasikan hasil yang tidak berperilaku seperti yang diharapkan.

Asumsikan Anda ingin membulatkan sesuatu ke sen terdekat. Jadi Anda mengambil hasil akhir Anda, kalikan dengan 100, tambahkan 0,5, truncate, kemudian bagi hasilnya dengan 100 untuk kembali ke sen. Jika nomor internal yang Anda simpan adalah 3,46499999 .... bukan 3,465, Anda akan mendapatkan 3,46 bukan 3,47 ketika Anda membulatkan angka ke sen terdekat. Tetapi perhitungan 10 dasar Anda mungkin telah mengindikasikan bahwa jawabannya harus tepat 3,465, yang jelas harus mengumpulkan hingga 3,47, tidak turun ke 3,46. Hal-hal semacam ini kadang-kadang terjadi dalam kehidupan nyata ketika Anda menggunakan ganda untuk perhitungan keuangan. Sangat jarang, sehingga sering tidak diperhatikan sebagai masalah, tetapi itu terjadi.

Jika Anda menggunakan basis 10 untuk perhitungan internal, bukan ganda, jawabannya selalu tepat seperti yang diharapkan oleh manusia, dengan asumsi tidak ada bug lain dalam kode Anda.


63
2017-09-12 15:11



Saya terganggu oleh beberapa tanggapan ini. Saya pikir ganda dan mengapung memiliki tempat dalam perhitungan keuangan. Tentu saja, ketika menambah dan mengurangi jumlah moneter non-pecahan tidak akan ada kehilangan presisi ketika menggunakan kelas integer atau kelas BigDecimal. Tetapi ketika melakukan operasi yang lebih kompleks, Anda sering berakhir dengan hasil yang keluar beberapa atau banyak tempat desimal, tidak peduli bagaimana Anda menyimpan angka. Masalahnya adalah bagaimana Anda menyajikan hasilnya.

Jika hasil Anda berada di garis batas antara dibulatkan ke atas dan dibulatkan ke bawah, dan sen terakhir itu benar-benar penting, Anda seharusnya memberi tahu pemirsa bahwa jawabannya hampir berada di tengah - dengan menampilkan lebih banyak tempat desimal.

Masalah dengan ganda, dan lebih lagi dengan pelampung, adalah ketika mereka digunakan untuk menggabungkan angka besar dan angka kecil. Di java,

System.out.println(1000000.0f + 1.2f - 1000000.0f);

hasil dalam

1.1875

40
2018-04-03 14:54



Mengapung dan ganda adalah perkiraan. Jika Anda membuat BigDecimal dan mengirimkan float ke konstruktor Anda melihat apa yang sebenarnya mengapung sama:

groovy:000> new BigDecimal(1.0F)
===> 1
groovy:000> new BigDecimal(1.01F)
===> 1.0099999904632568359375

ini mungkin bukan bagaimana Anda ingin mewakili $ 1,01.

Masalahnya adalah bahwa spesifikasi IEEE tidak memiliki cara untuk merepresentasikan semua fraksi, beberapa dari mereka berakhir sebagai fraksi berulang sehingga Anda berakhir dengan kesalahan aproksimasi. Karena akuntan menyukai hal-hal untuk keluar persis dengan sen, dan pelanggan akan terganggu jika mereka membayar tagihan mereka dan setelah pembayaran diproses mereka berhutang .01 dan mereka dikenakan biaya atau tidak dapat menutup akun mereka, lebih baik menggunakan jenis yang tepat seperti desimal (dalam C #) atau java.math.BigDecimal di Java.

Bukan berarti kesalahan tidak dapat dikontrol jika Anda membulatkan: lihat artikel ini oleh Peter Lawrey. Lebih mudah untuk tidak membulatkan tempat pertama. Sebagian besar aplikasi yang menangani uang tidak membutuhkan banyak perhitungan, operasi terdiri dari menambahkan sesuatu atau mengalokasikan jumlah ke berbagai ember. Memperkenalkan floating point dan pembulatan hanya memperumit keadaan.


35
2017-09-16 19:29



Hasil dari angka floating point tidak tepat, yang membuat mereka tidak cocok untuk perhitungan keuangan yang memerlukan hasil yang tepat dan bukan perkiraan. float dan double dirancang untuk rekayasa dan perhitungan ilmiah dan sering kali tidak menghasilkan hasil yang tepat juga hasil perhitungan floating point dapat bervariasi dari JVM ke JVM. Lihatlah contoh di bawah BigDecimal dan double primitive yang digunakan untuk merepresentasikan nilai uang, cukup jelas bahwa perhitungan floating point mungkin tidak tepat dan orang harus menggunakan BigDecimal untuk perhitungan finansial.

    // floating point calculation
    final double amount1 = 2.0;
    final double amount2 = 1.1;
    System.out.println("difference between 2.0 and 1.1 using double is: " + (amount1 - amount2));

    // Use BigDecimal for financial calculation
    final BigDecimal amount3 = new BigDecimal("2.0");
    final BigDecimal amount4 = new BigDecimal("1.1");
    System.out.println("difference between 2.0 and 1.1 using BigDecimal is: " + (amount3.subtract(amount4)));

Keluaran:

difference between 2.0 and 1.1 using double is: 0.8999999999999999
difference between 2.0 and 1.1 using BigDecimal is: 0.9

15
2017-08-11 20:18



Meskipun benar bahwa tipe titik apung dapat mewakili hanya data desimal yang mendekati, itu juga benar bahwa jika satu putaran angka ke presisi yang diperlukan sebelum menampilkannya, seseorang mendapatkan hasil yang benar. Biasanya.

Biasanya karena tipe double memiliki presisi kurang dari 16 angka. Jika Anda membutuhkan ketelitian yang lebih baik, itu bukan tipe yang cocok. Juga perkiraan bisa terakumulasi.

Harus dikatakan bahwa bahkan jika Anda menggunakan aritmatika titik tetap Anda masih harus membulatkan angka, kalau bukan karena fakta bahwa BigInteger dan BigDecimal memberikan kesalahan jika Anda mendapatkan angka desimal periodik. Jadi ada perkiraan juga di sini.

Misalnya COBOL, yang secara historis digunakan untuk perhitungan keuangan, memiliki presisi maksimum 18 angka. Jadi sering ada pembulatan implisit.

Kesimpulannya, menurut saya, dobel itu tidak cocok terutama untuk presisi 16 digit, yang bisa tidak cukup, bukan karena perkiraan.

Pertimbangkan keluaran berikut dari program berikutnya. Ini menunjukkan bahwa setelah pembulatan ganda memberikan hasil yang sama seperti BigDecimal hingga presisi 16.

Precision 14
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.000051110111115611
Double                        : 56789.012345 / 1111111111 = 0.000051110111115611

Precision 15
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.0000511101111156110
Double                        : 56789.012345 / 1111111111 = 0.0000511101111156110

Precision 16
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.00005111011111561101
Double                        : 56789.012345 / 1111111111 = 0.00005111011111561101

Precision 17
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.000051110111115611011
Double                        : 56789.012345 / 1111111111 = 0.000051110111115611013

Precision 18
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.0000511101111156110111
Double                        : 56789.012345 / 1111111111 = 0.0000511101111156110125

Precision 19
------------------------------------------------------
BigDecimalNoRound             : 56789.012345 / 1111111111 = Non-terminating decimal expansion; no exact representable decimal result.
DoubleNoRound                 : 56789.012345 / 1111111111 = 5.111011111561101E-5
BigDecimal                    : 56789.012345 / 1111111111 = 0.00005111011111561101111
Double                        : 56789.012345 / 1111111111 = 0.00005111011111561101252

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.MathContext;

public class Exercise {
    public static void main(String[] args) throws IllegalArgumentException,
            SecurityException, IllegalAccessException,
            InvocationTargetException, NoSuchMethodException {
        String amount = "56789.012345";
        String quantity = "1111111111";
        int [] precisions = new int [] {14, 15, 16, 17, 18, 19};
        for (int i = 0; i < precisions.length; i++) {
            int precision = precisions[i];
            System.out.println(String.format("Precision %d", precision));
            System.out.println("------------------------------------------------------");
            execute("BigDecimalNoRound", amount, quantity, precision);
            execute("DoubleNoRound", amount, quantity, precision);
            execute("BigDecimal", amount, quantity, precision);
            execute("Double", amount, quantity, precision);
            System.out.println();
        }
    }

    private static void execute(String test, String amount, String quantity,
            int precision) throws IllegalArgumentException, SecurityException,
            IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
        Method impl = Exercise.class.getMethod("divideUsing" + test, String.class,
                String.class, int.class);
        String price;
        try {
            price = (String) impl.invoke(null, amount, quantity, precision);
        } catch (InvocationTargetException e) {
            price = e.getTargetException().getMessage();
        }
        System.out.println(String.format("%-30s: %s / %s = %s", test, amount,
                quantity, price));
    }

    public static String divideUsingDoubleNoRound(String amount,
            String quantity, int precision) {
        // acceptance
        double amount0 = Double.parseDouble(amount);
        double quantity0 = Double.parseDouble(quantity);

        //calculation
        double price0 = amount0 / quantity0;

        // presentation
        String price = Double.toString(price0);
        return price;
    }

    public static String divideUsingDouble(String amount, String quantity,
            int precision) {
        // acceptance
        double amount0 = Double.parseDouble(amount);
        double quantity0 = Double.parseDouble(quantity);

        //calculation
        double price0 = amount0 / quantity0;

        // presentation
        MathContext precision0 = new MathContext(precision);
        String price = new BigDecimal(price0, precision0)
                .toString();
        return price;
    }

    public static String divideUsingBigDecimal(String amount, String quantity,
            int precision) {
        // acceptance
        BigDecimal amount0 = new BigDecimal(amount);
        BigDecimal quantity0 = new BigDecimal(quantity);
        MathContext precision0 = new MathContext(precision);

        //calculation
        BigDecimal price0 = amount0.divide(quantity0, precision0);

        // presentation
        String price = price0.toString();
        return price;
    }

    public static String divideUsingBigDecimalNoRound(String amount, String quantity,
            int precision) {
        // acceptance
        BigDecimal amount0 = new BigDecimal(amount);
        BigDecimal quantity0 = new BigDecimal(quantity);

        //calculation
        BigDecimal price0 = amount0.divide(quantity0);

        // presentation
        String price = price0.toString();
        return price;
    }
}

14
2017-10-26 19:03



Saya akan mengambil risiko untuk kalah suara, tetapi saya pikir ketidaksesuaian angka floating point untuk perhitungan mata uang terlalu tinggi. Selama Anda memastikan bahwa Anda melakukan pembulatan dengan benar dan memiliki cukup banyak angka untuk bekerja dalam rangka melawan ketidakcocokan representasi biner-desimal yang dijelaskan oleh zneak, tidak akan ada masalah.

Orang yang menghitung dengan mata uang di Excel selalu menggunakan pelapis presisi ganda (tidak ada jenis mata uang di Excel) dan saya belum melihat ada yang mengeluh tentang kesalahan pembulatan.

Tentu saja, Anda harus tetap dalam alasan; misalnya sebuah toko web sederhana mungkin tidak akan pernah mengalami masalah dengan pelapisan presisi ganda, tetapi jika Anda melakukan mis. akuntansi atau hal lain yang membutuhkan penambahan jumlah nomor yang besar (tidak terbatas), Anda tidak ingin menyentuh angka titik mengambang dengan tiang sepuluh kaki.


10
2018-01-20 11:56



Seperti yang dikatakan sebelumnya "Mewakili uang sebagai double atau float mungkin akan terlihat bagus pada awalnya karena perangkat lunak membulatkan kesalahan kecil, tetapi ketika Anda melakukan lebih banyak penambahan, pengurangan, perkalian dan pembagian pada nomor yang tidak sama, Anda akan kehilangan lebih banyak dan lebih tepat karena kesalahannya bertambah. Ini membuat pelampung dan ganda tidak memadai untuk berurusan dengan uang, di mana akurasi sempurna untuk kelipatan kekuatan basis 10 dibutuhkan. "

Akhirnya Java memiliki cara standar untuk bekerja dengan Mata Uang dan Uang!

JSR 354: Uang dan Mata Uang API

JSR 354 menyediakan API untuk mewakili, mengangkut, dan melakukan perhitungan komprehensif dengan Uang dan Mata Uang. Anda dapat mengunduhnya dari tautan ini:

JSR 354: Unduhan Uang dan Mata Uang API

Spesifikasi terdiri dari hal-hal berikut:

  1. API untuk menangani e. g. jumlah uang dan mata uang
  2. API untuk mendukung implementasi yang dapat dipertukarkan
  3. Pabrik untuk membuat instance dari kelas implementasi
  4. Fungsionalitas untuk perhitungan, konversi dan pemformatan jumlah uang
  5. Java API untuk bekerja dengan Uang dan Mata Uang, yang rencananya akan dimasukkan ke dalam Java 9.
  6. Semua kelas spesifikasi dan antarmuka terletak di paket javax.money. *.

Contoh Contoh JSR 354: Uang dan Mata Uang API:

Contoh pembuatan MonetaryAmount dan mencetaknya ke konsol terlihat seperti ini ::

MonetaryAmountFactory<?> amountFactory = Monetary.getDefaultAmountFactory();
MonetaryAmount monetaryAmount = amountFactory.setCurrency(Monetary.getCurrency("EUR")).setNumber(12345.67).create();
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.getDefault());
System.out.println(format.format(monetaryAmount));

Saat menggunakan API implementasi referensi, kode yang diperlukan jauh lebih sederhana:

MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR");
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.getDefault());
System.out.println(format.format(monetaryAmount));

API juga mendukung perhitungan dengan MonetaryAmounts:

MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR");
MonetaryAmount otherMonetaryAmount = monetaryAmount.divide(2).add(Money.of(5, "EUR"));

CurrencyUnit dan MonetaryAmount

// getting CurrencyUnits by locale
CurrencyUnit yen = MonetaryCurrencies.getCurrency(Locale.JAPAN);
CurrencyUnit canadianDollar = MonetaryCurrencies.getCurrency(Locale.CANADA);

MonetaryAmount memiliki berbagai metode yang memungkinkan mengakses mata uang yang ditetapkan, jumlah numerik, ketepatannya, dan banyak lagi:

MonetaryAmount monetaryAmount = Money.of(123.45, euro);
CurrencyUnit currency = monetaryAmount.getCurrency();
NumberValue numberValue = monetaryAmount.getNumber();

int intValue = numberValue.intValue(); // 123
double doubleValue = numberValue.doubleValue(); // 123.45
long fractionDenominator = numberValue.getAmountFractionDenominator(); // 100
long fractionNumerator = numberValue.getAmountFractionNumerator(); // 45
int precision = numberValue.getPrecision(); // 5

// NumberValue extends java.lang.Number. 
// So we assign numberValue to a variable of type Number
Number number = numberValue;

MonetaryAmount dapat dibulatkan menggunakan operator pembulatan:

CurrencyUnit usd = MonetaryCurrencies.getCurrency("USD");
MonetaryAmount dollars = Money.of(12.34567, usd);
MonetaryOperator roundingOperator = MonetaryRoundings.getRounding(usd);
MonetaryAmount roundedDollars = dollars.with(roundingOperator); // USD 12.35

Ketika bekerja dengan koleksi MonetaryAmounts, beberapa metode utilitas yang bagus untuk menyaring, menyortir, dan pengelompokan tersedia.

List<MonetaryAmount> amounts = new ArrayList<>();
amounts.add(Money.of(2, "EUR"));
amounts.add(Money.of(42, "USD"));
amounts.add(Money.of(7, "USD"));
amounts.add(Money.of(13.37, "JPY"));
amounts.add(Money.of(18, "USD"));

Operasi Moneter KhususAmount

// A monetary operator that returns 10% of the input MonetaryAmount
// Implemented using Java 8 Lambdas
MonetaryOperator tenPercentOperator = (MonetaryAmount amount) -> {
  BigDecimal baseAmount = amount.getNumber().numberValue(BigDecimal.class);
  BigDecimal tenPercent = baseAmount.multiply(new BigDecimal("0.1"));
  return Money.of(tenPercent, amount.getCurrency());
};

MonetaryAmount dollars = Money.of(12.34567, "USD");

// apply tenPercentOperator to MonetaryAmount
MonetaryAmount tenPercentDollars = dollars.with(tenPercentOperator); // USD 1.234567

Sumber daya:

Penanganan uang dan mata uang di Jawa dengan JSR 354

Melihat ke dalam API Uang dan Mata Uang 9 Java (JSR 354)

Lihat juga: JSR 354 - Mata Uang dan Uang


9
2017-08-07 07:08



Jika perhitungan Anda melibatkan berbagai langkah, aritmatika presisi sewenang-wenang tidak akan mencakup Anda 100%.

Satu-satunya cara yang dapat diandalkan untuk menggunakan representasi sempurna dari hasil (Gunakan tipe data Fraksi kustom yang akan membagi operasi batch ke langkah terakhir) dan hanya mengkonversi ke notasi desimal pada langkah terakhir.

Presisi yang sewenang-wenang tidak akan membantu karena selalu bisa ada angka yang memiliki banyak tempat desimal, atau beberapa hasil seperti 0,6666666 ... Tidak ada representasi arbitrer akan mencakup contoh terakhir. Jadi Anda akan memiliki kesalahan kecil di setiap langkah.

Kesalahan ini akan bertambah, mungkin akhirnya menjadi tidak mudah diabaikan lagi. Ini disebut Error Propagation.


2
2018-01-05 14:56



Saya lebih suka menggunakan Integer atau Long untuk mewakili mata uang. BigDecimal menjejalkan kode sumber terlalu banyak.

Anda hanya perlu tahu bahwa semua nilai Anda dalam sen. Atau nilai terendah dari mata uang apa pun yang Anda gunakan.


1
2017-09-18 04:47