Sistem::Pembuat Mata Uang dan C++

Saya menggunakan Embarcadero C++ Builder XE10 untuk membangun aplikasi yang melakukan beberapa perhitungan moneter.

Saat mencoba menggunakan tipe data System::Currency saya menghadapi beberapa masalah.

Q1: Mengapa penghitungan modulus gagal saat menggunakan operator "%"?

System::Currency TaxValue = 1.665;
System::Currency Rest = 0;

// Correct result: Rest will be 0.005 when converted to double
Rest = TaxValue - ( TaxValue / 100 * 100 );

// Incorrect result: Rest is the same as TaxValue
Rest = TaxValue % 100;

Sunting: Saya benar-benar tertipu oleh keluaran debugger di mana nilai System::Currency ditampilkan dalam representasi bilangan bulat dikalikan 10.000.

Apa yang sebenarnya saya harapkan adalah:

Rest = (TaxValue * 10000) % 100;

==> Sekarang Istirahatnya adalah 50, persis seperti yang saya harapkan.

Q2: Bagaimana cara melakukan pembulatan bankir yang benar dengan tipe data Curreny?

Contoh:

1.664 => 1.66
1.665 => 1.67
1.666 => 1.67

Herwig


person Herwig    schedule 24.04.2017    source sumber
comment
System::Currency bukan bagian dari standar C++. Apakah Anda kebetulan mengkompilasi sebagai C++/CLI dan bukan C++?   -  person Algirdas Preidžius    schedule 24.04.2017
comment
Aku tahu. System::Currency adalah bagian dari Kerangka Borland/Embarcadero.   -  person Herwig    schedule 24.04.2017
comment
Oh begitu. Dalam hal ini - harap uraikan hasil yang salah. Yaitu. Apa yang Anda harapkan, apa yang Anda dapatkan, mengapa Anda mengharapkan kode tersebut berperilaku berbeda.   -  person Algirdas Preidžius    schedule 24.04.2017
comment
Hasilnya benar, oleh karena itu pertanyaan saya tidak sah (kata lain bodoh). Saya telah disesatkan oleh keluaran debugger, di mana setiap nilai System::Currency ditampilkan dalam representasi integernya dikalikan 10.000.   -  person Herwig    schedule 26.04.2017


Jawaban (1)


Q1: Mengapa penghitungan modulus gagal saat menggunakan operator "%"?

System::Currency beroperasi dengan presisi 4 tempat desimal. Contoh Anda mengharapkan presisi 2 digit.

System::Currency mempertahankan presisinya tanpa kesalahan pembulatan dengan mengalikan nilai masukan secara internal dengan 10000 lalu menggunakan matematika bilangan bulat alih-alih matematika titik-mengambang untuk memanipulasi nilai.

Saat Anda menginisialisasi TaxValue dengan 1.665, anggota Val internalnya (yang merupakan __int64) disetel ke (1.665 * 10000) = 16650. Berikut tampilan konstruktornya:

__fastcall Currency(double val) {Val = _roundToInt64(10000 * val);}

Saat Anda menjalankan TaxValue % 100, operator % diimplementasikan seperti ini:

Currency __fastcall operator %(int rhs) const
{return Currency(static_cast<int>(Val % (10000 * (__int64)rhs))) / 10000;}

Bagian pertama membuat objek temp Currency yang diinisialisasi dengan nilai int sebesar (16650 % (10000 * 100)) = 16650, yang dikalikan dengan 10000 hingga 166500000 oleh konstruktor objek temp:

__fastcall Currency(int val) {Val = 10000*(__int64)val;}

Bagian kedua kemudian membagi suhu dengan 10000. Operator / diimplementasikan seperti ini:

Currency& __fastcall operator /=(const Currency& rhs)
{Val *= 10000; Val /= rhs.Val; return *this;}

Currency __fastcall operator /(int rhs) const
{Currency tmp(*this); return tmp /= Currency(rhs);}

Sehingga menghasilkan objek Currency akhir yang Val-nya telah disetel ke (166500000 * 10000) / (10000 * 10000) = 16650.

Ketika Currency akhir tersebut kemudian ditetapkan ke Rest dan dikonversi ke double, nilainya dibagi dengan 10000, sehingga menghasilkan 1.665:

__fastcall operator double() const {return ((double)Val) / 10000;}

Q2: Bagaimana cara melakukan pembulatan bankir yang benar dengan tipe data Curreny?

Lihat fungsi System::Round() yang menggunakan pembulatan bankir.

Jika Anda ingin lebih mengontrol pembulatan, gunakan fungsi System::Math::RoundTo(), atau cari fungsi pembulatan pihak ketiga.

Ada beberapa pertanyaan lain di StackOverflow yang berhubungan dengan pembulatan Currency, misalnya:

Bagaimana cara membuat Jenis Mata Uang Delphi selalu Bulat seperti Excel?

pembulatan mata uang

(System::Currency adalah pembungkus C++Builder untuk tipe Currency asli Delphi).

person Remy Lebeau    schedule 25.04.2017