Forum Linux.pl

Programowanie => C/C++ => Wątek zaczęty przez: MateuszA w 2016-10-12, 22:36:09

Tytuł: jak w C++ robić operacje na pieniądzach
Wiadomość wysłana przez: MateuszA w 2016-10-12, 22:36:09
Paweł mam pytanie kiedyś mi napisałeś że jest specjalne miejsce dla ludzi którzy do obliczeń finansowych używają float double i temu podobnych. A teraz chciałbym się zabrać za tą część programu możesz mi coś poradzić?
Tytuł: Odp: jak w C++ robić operacje na pieniądzach
Wiadomość wysłana przez: Paweł Kraszewski w 2016-10-13, 06:16:11
Najprościej trzymać kwotę wyrażoną w groszach (albo dziesiątych/setnych grosza, jak trzeba większej kontroli nad zaokrąglaniem) na dużym int, np int64_t. Jest to metoda nazywana "decimal fixed point" albo w skrócie typ decimal.

Dobrym ćwiczeniem byłoby zawinięcie tego w klasę z implementacja operatorów arytmetycznych i wyjścia-wejścia.
Tytuł: Odp: jak w C++ robić operacje na pieniądzach
Wiadomość wysłana przez: MateuszA w 2016-10-13, 21:13:58
Czyli chodzi o to ze zł to int i grosze to int a później to się łączy? Czy dobrze rozumiem.
Tytuł: Odp: jak w C++ robić operacje na pieniądzach
Wiadomość wysłana przez: Paweł Kraszewski w 2016-10-13, 21:24:01
Nie. W ogóle nie posługujesz się złotówkami. 15.50 zł to 1550 groszy i trzymasz to jako 1550 w int. Wszystkie operacje typu dodawanie i odejmowanie wartości oraz mnożenie i dzielenie wartości przez skalar (żeby nie mieć groszy kwadratowych) działają poprawnie, tylko trzeba pamiętać, że wynik to x/100 złotych i x%100 groszy.
Tytuł: Odp: jak w C++ robić operacje na pieniądzach
Wiadomość wysłana przez: MateuszA w 2016-10-13, 21:38:04
A mam takie pytanie bo mam coś takiego do napisania jak smart saver. Jest to opcja w banku która zaokrągla wydane pieniądze do pełnej liczby i resztę przelewa na konto oszczędnościowe. chodzi o to gdy place kartą np. 33,33 to bank bierze to jako 35 zl i od tego odejmuje 33,33 i 1,67 przelewa na konto lub jak place 16 zl to na konto oszczędnościowe przelewają mi 4zł. I to chciałem zrobić ze mam grosze osobno i odejmuj je od 100 i reszta to grosze na konto i dodaje jeden do części zł a później zł dodaje tak długo aż będzie podzielne przez 5.
Tytuł: Odp: jak w C++ robić operacje na pieniądzach
Wiadomość wysłana przez: Paweł Kraszewski w 2016-10-14, 09:16:44
money.h
#ifndef MONEY_H
#define MONEY_H

#include <inttypes.h>
#include <iomanip>
#include <iostream>

template <typename T>
class Money {
 private:
  T amount;

 public:

  // Konstruktory
  Money() : amount( 0 ) {}
  Money( const Money<T>& m ) : amount( m.amount ) {}

  // Explicit daje to, że nie robią się automatyczne konwersje typów
  explicit Money( T am ) : amount( am ) {}
  explicit Money( double d ) : amount( d * 100 ) {}

  // Operator przypisanie

  Money<T>& operator=( const Money<T>& m ) { amount = m.amount; }
  Money<T>& operator=( T am ) { amount = am; }

  // Dodawać i odejmować mozemy tylko 2 obiekty Money

  inline friend Money<T> operator+( const Money<T>& m1, const Money<T>& m2 ) {
    return Money<T>( m1.amount + m2.amount );
  }
  inline friend Money<T> operator-( const Money<T>& m1, const Money<T>& m2 ) {
    return Money<T>( m1.amount - m2.amount );
  }

  // W mnożeniu i dzieleniu drugi argument NIE JEST typu Money.
  // Dzięki temu Money64(5.0)*5 działa jak oczekiwano, dając 25zł

  inline friend Money<T> operator*( const Money<T>& m1, double v ) {
    return Money<T>( T( m1.amount * v ) );
  }

  inline friend Money<T> operator/( const Money<T>& m1, double v ) {
    return Money<T>( T( m1.amount / v ) );
  }

  // Argumenty w odwrotnej kolejności, dzielenie nie ma sensu.

  inline friend Money<T> operator*( double v, const Money<T>& m1 ) {
    return Money<T>( T( m1.amount * v ) );
  }

  // Wyświetlenie sformatowanej wartości

  inline friend std::ostream& operator<<( std::ostream& o, const Money<T>& m ) {
    return ( o << ( m.amount / 100 ) << '.' << std::setfill( '0' )
               << std::setw( 2 ) << ( m.amount % 100 ) )<<" PLN";
  }

  // Zaokrąglenie w górę

  inline Money<T> RoundUp( Money<T> to ) const {
    T r = to.amount * T( ( amount + to.amount - 1 ) / to.amount );
    return Money<T>( r );
  }

  // Explicit wyłącza automatyczne rzutowanie.
  // Nie działa
  //  Money64 M(5.0);
  //  double d = M;
  // Trzeba zrobić
  //  double d = static_cast<double>(M);
  //
  // Upierdliwe, ale pozwala uniknąć błędów gdy coś się automatycznie ale
  // nieplanowo zrzutuje w tle.
  explicit operator double() const { return double( amount ) / 100.0; }
  explicit operator T() const { return amount / 100; }
};

// Rozmiar 64bity
typedef Money<int64_t> Money64;

// Rozmiar 32bity
typedef Money<int32_t> Money32;

#endif  // MONEY_H

main.cpp
#include "money.h"
#include <iostream>

using std::cout;
using std::endl;

int main( int argc, char *argv[] ) {
  Money64 m1( 3.50 );
  Money64 m2( 13.0 );
  Money64 m3 = m1 + m2;

  cout << "M1=" << m1 << endl;
  cout << "M2=" << m2 << endl;
  cout << "M1+M2=" << m3 << endl;

  cout << m3 << " zaokrąglone w górę do 1zł=" << m3.RoundUp( Money64( 1.0 ) )
       << " reszta " << m3.RoundUp( Money64( 1.0 ) ) - m3 << endl;
  cout << m3 << " zaokrąglone w górę do 5zł=" << m3.RoundUp( Money64( 5.0 ) )
       << " reszta " << m3.RoundUp( Money64( 5.0 ) ) - m3 << endl;
  cout << m3 << "  zaokrąglone w górę do 50zł=" << m3.RoundUp( Money64( 50.0 ) )
       << " reszta " << m3.RoundUp( Money64( 50.0 ) ) - m3 << endl;

  cout << m3 << " * 3 = " << m3 * 3 << endl;
  cout << "3 * " << m3 << " = " << 3 * m3 << endl;

  cout << m3 << " / 3 = " << m3 / 3 << endl;

  return 0;
}

Wynik
M1=3.50 PLN
M2=13.00 PLN
M1+M2=16.50 PLN
16.50 PLN zaokrąglone w górę do 1zł=17.00 PLN reszta 0.50 PLN
16.50 PLN zaokrąglone w górę do 5zł=20.00 PLN reszta 3.50 PLN
16.50 PLN  zaokrąglone w górę do 50zł=50.00 PLN reszta 33.50 PLN
16.50 PLN * 3 = 49.50 PLN
3 * 16.50 PLN = 49.50 PLN
16.50 PLN / 3 = 5.50 PLN
Tytuł: Odp: jak w C++ robić operacje na pieniądzach
Wiadomość wysłana przez: MateuszA w 2016-11-16, 16:40:00
Powiem tak nie bardzo to rozumiem :D
Tytuł: Odp: jak w C++ robić operacje na pieniądzach
Wiadomość wysłana przez: Mateusz Leśmian w 2019-11-13, 14:00:35
też się chyba jeszcze muszę podszkolić
__________________________
http://trans-ziem.pl/