Decimal for C++
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.12.20 14:58
Оценка:
Здравствуйте!

Неохота было что-то искать, накидал на скорую руку

#pragma once


#include <string>
#include <cstdint>
#include <utility>
#include <limits>
#include <iostream>
#include <exception>
#include <stdexcept>


//----------------------------------------------------------------------------
namespace marty
{



//----------------------------------------------------------------------------
// 4 294 967 295 uint32_t max
// 1 000 000 000 - must be enough for money or use more wide type in typedef below

typedef std::uint32_t  DecimalDenumeratorRawType;
typedef std::int32_t   DecimalDenumeratorSignedRawType;

//----------------------------------------------------------------------------
//  9 223 372 036 854 775 808
//  1 000 000 000.000 000  000 - 10**9 -  миллиард - бюджет страны верстать не выйдет с точностью 9 нулей после точки
//  1 000 000 000 000 00.0 000 - 10**15 - 100 трлн с точностью до сотых копейки - для домашней бухгалтерии норм

typedef std::int64_t   DecimalNumeratorRawType;



//----------------------------------------------------------------------------
class DecimalDenumerator;

class DecimalPrecision
{
    friend class DecimalDenumerator;

    std::uint32_t m_precision;

    // default constructor disabled
    DecimalPrecision( );
    //DecimalPrecision& operator=( const DecimalPrecision &dp );

public:

    typedef std::uint32_t                    precision_t;
    typedef DecimalDenumeratorRawType        denum_t;
    typedef DecimalDenumeratorSignedRawType  sdenum_t;

    static denum_t denum( precision_t pr )
    {
        if ( maxPrecision<denum_t>() < pr )
            throw std::runtime_error("DecimalPrecision::denum - taken precision to big");

        return (denum_t)(getPowers10Table()[pr]);

        /*
        denum_t  denum = 1;
        for(precision_t i=0; i!=pr; ++i)
        {
            denum_t next = denum * 10u;
            if (next<denum)
                throw std::runtime_error("DecimalPrecision precision to big");
            denum = next;
        }

        return denum;
        */
    }

    DecimalPrecision( std::uint32_t pr ) : m_precision(pr) {}
    DecimalPrecision( const DecimalPrecision &pr ) : m_precision(pr.m_precision) {}

    denum_t denum( ) const
    {
        return denum(m_precision);
    }

    precision_t prec() const 
    {
        return m_precision;
    }

protected:

    template<typename IntType>
    static precision_t maxPrecision()    { throw std::runtime_error("DecimalPrecision::maxPrecision not implemented"); }

    template<> static precision_t maxPrecision<std::int32_t >() { return  9; }
    template<> static precision_t maxPrecision<std::uint32_t>() { return  9; }
    template<> static precision_t maxPrecision<std::int64_t >() { return 18; }
    template<> static precision_t maxPrecision<std::uint64_t>() { return 18; }


    static std::uint64_t* getPowers10Table()
    {
        static std::uint64_t _[] = 
        { 1                             //  0
        , 10                            //  1
        , 100                           //  2
        , 1000                          //  3
        , 10000                         //  4
        , 100000                        //  5
        , 1000000                       //  6
        , 10000000                      //  7
        , 100000000                     //  8
        , 1000000000                    //  9 - max for int32_t
        , 10000000000                   // 10
        , 100000000000                  // 11
        , 1000000000000                 // 12
        , 10000000000000                // 13
        , 100000000000000               // 14
        , 1000000000000000              // 15
        , 10000000000000000             // 16
        , 100000000000000000            // 17
        , 1000000000000000000           // 18 - max for int64_t
        };
    
        return &_[0];
    }


}; // class DecimalPrecision

//----------------------------------------------------------------------------



#define MARTY_DECIMAL_IMPLEMENT_RELATIONAL_OPERATORS( typeT2 )\
                                                              \
    bool operator<( const typeT2 v2 ) const                   \
    {                                                         \
        return compare(v2)<0;                                 \
    }                                                         \
                                                              \
    bool operator<=( const typeT2 v2 ) const                  \
    {                                                         \
        return compare(v2)<=0;                                \
    }                                                         \
                                                              \
    bool operator>( const typeT2 v2 ) const                   \
    {                                                         \
        return compare(v2)>0;                                 \
    }                                                         \
                                                              \
    bool operator>=( const typeT2 v2 ) const                  \
    {                                                         \
        return compare(v2)>=0;                                \
    }                                                         \
                                                              \
    bool operator==( const typeT2 v2 ) const                  \
    {                                                         \
        return compare(v2)==0;                                \
    }                                                         \
                                                              \
    bool operator!=( const typeT2 v2 ) const                  \
    {                                                         \
        return compare(v2)!=0;                                \
    }





//----------------------------------------------------------------------------
class Decimal;

class DecimalDenumerator
{

public:

    typedef DecimalPrecision::denum_t       denum_t    ;
    typedef DecimalPrecision::sdenum_t      sdenum_t   ;
    typedef DecimalPrecision::precision_t   precision_t;

    friend class Decimal;

    DecimalDenumerator( const DecimalPrecision dp )
    : m_precision( dp.prec() )
    , m_denum    ( dp.denum() )
    {}

    DecimalDenumerator( const DecimalDenumerator &dd )
    : m_precision( dd.m_precision )
    , m_denum    ( dd.m_denum     )
    {}

    DecimalDenumerator& operator=( const DecimalDenumerator &dd )
    {
        m_precision = dd.m_precision;
        m_denum     = dd.m_denum    ;
        return *this;
    }

    precision_t prec () const { return m_precision; }
    denum_t     denum() const { return m_denum; }

    DecimalPrecision decimalPrecision( ) const { return DecimalPrecision(m_precision); }

    void swap( DecimalDenumerator &d2 )
    {
        //using namespace std;
        std::swap( m_precision, d2.m_precision );
        std::swap( m_denum    , d2.m_denum     );
    }

    int compare( const DecimalDenumerator d2 ) const
    {
        if (m_precision<d2.m_precision) return -1;
        if (m_precision>d2.m_precision) return  1;
        return 0;
    }

    MARTY_DECIMAL_IMPLEMENT_RELATIONAL_OPERATORS(DecimalDenumerator)


protected:

    void incPrec()
    {
        tryIncDenum();
        m_precision += 1;
    }

    void decPrec()
    {
        tryDecDenum();
        m_precision -= 1;
    }

    denum_t expandTo( precision_t p )
    {
        denum_t deltaDenum = 1;
        while(m_precision < p)
        {
            incPrec();
            deltaDenum *= 10;
        }

        return deltaDenum;
    }

    denum_t shrinkTo( precision_t p )
    {
        denum_t deltaDenum = 1;
        while(m_precision > p)
        {
            decPrec();
            deltaDenum *= 10;
        }

        return deltaDenum;
    }

    sdenum_t fitTo( precision_t p )
    {
        if (m_precision<p)
            return   (sdenum_t)expandTo(p);
        else
            return - (sdenum_t)shrinkTo(p);
    }


    void tryIncDenum()
    {
        denum_t newDenum = m_denum*10u;
        if (newDenum<m_denum)
            throw std::runtime_error("DecimalDenumerator precision to big to increment");
        m_denum = newDenum;
    }

    void tryDecDenum()
    {
        if (!m_denum)
            throw std::runtime_error("DecimalDenumerator precision to small to decrement");
        m_denum = m_denum / 10u;
    }


    // default constructor disabled
    DecimalDenumerator();

    precision_t  m_precision;
    denum_t      m_denum;

}; // class DecimalDenumerator

//----------------------------------------------------------------------------




//----------------------------------------------------------------------------
inline
void swap( DecimalDenumerator &d1, DecimalDenumerator &d2 )
{
    d1.swap( d2 );
}

//----------------------------------------------------------------------------




//----------------------------------------------------------------------------
std::string toString  ( const Decimal     &d );
Decimal     fromString( const std::string &d );
void swap( Decimal &d1, Decimal &d2 );

//----------------------------------------------------------------------------




//----------------------------------------------------------------------------
class Decimal
{

    friend std::string toString  ( const Decimal     &d );
    friend Decimal     fromString( const std::string &d );
    friend void swap( Decimal &d1, Decimal &d2 );


public:

    typedef DecimalNumeratorRawType           num_t      ;
    typedef DecimalDenumerator::denum_t       denum_t    ;
    typedef DecimalDenumerator::sdenum_t      sdenum_t   ;
    typedef DecimalDenumerator::precision_t   precision_t;

    typedef DecimalDenumerator                DenumeratorType;

    Decimal()                   : m_num(0)      , m_denum(DecimalPrecision(0))   {}
    Decimal( const Decimal &d ) : m_num(d.m_num), m_denum(d.m_denum)             {}
    Decimal( int            v, const DecimalPrecision &prec = DecimalPrecision(0) ) : m_num(v), m_denum(prec) { m_num *= m_denum.denum(); }
    Decimal( unsigned       v, const DecimalPrecision &prec = DecimalPrecision(0) ) : m_num(v), m_denum(prec) { m_num *= m_denum.denum(); }
    Decimal( std::int64_t   v, const DecimalPrecision &prec = DecimalPrecision(0) ) : m_num(v), m_denum(prec) { m_num *= m_denum.denum(); }
    Decimal( std::uint64_t  v, const DecimalPrecision &prec = DecimalPrecision(0) ) : m_num(v), m_denum(prec) { m_num *= m_denum.denum(); }

    Decimal( float          f, const DecimalPrecision &prec = DecimalPrecision(0) )
    : m_num(0), m_denum(prec)
    {
        fromFloat( f, prec );
    }

    Decimal( double          f, const DecimalPrecision &prec = DecimalPrecision(0) )
    : m_num(0), m_denum(prec)
    {
        fromFloat( f, prec );
    }

    void swap( Decimal &d2 )
    {
        //using namespace std;
        std::swap( m_num   , d2.m_num   );
        m_denum.swap( d2.m_denum );
    }


    Decimal& operator=( Decimal d2 )
    {
        swap(d2);
        return *this;
    }

    // операторы преобразования типа 

    explicit operator int() const
    {
        return (int)(m_num/m_denum.denum());
    }

    explicit operator unsigned() const
    {
        return (unsigned)(m_num/m_denum.denum());
    }

    explicit operator std::int64_t() const
    {
        return (m_num/m_denum.denum());
    }

    explicit operator std::uint64_t() const
    {
        return (std::uint64_t)(m_num/m_denum.denum());
    }

    explicit operator float() const
    {
        return (float)((double)m_num/(double)m_denum.denum());
    }

    explicit operator double() const
    {
        return ((double)m_num/(double)m_denum.denum());
    }


    Decimal operator + ( Decimal d2 ) const
    {
        Decimal d1 = *this;
        adjustPrecisions( d1, d2 );
        d1.m_num += d2.m_num;
        return d1;
    }

    Decimal operator - ( Decimal d2 ) const
    {
        Decimal d1 = *this;
        adjustPrecisions( d1, d2 );
        d1.m_num -= d2.m_num;
        return d1;
    }

    Decimal operator * ( Decimal d2 ) const
    {
        num_t num = m_num * d2.m_num;

        if (m_denum < d2.m_denum)
        {
            num /= m_denum.denum();
            return Decimal( num, d2.m_denum );
        }
        else
        {
            num /= d2.m_denum.denum();
            return Decimal( num, m_denum );
        }
    }

    // 1200.00000 / 22.000 = 54.5454545454545
    // 1200 00000 / 22 000 = 5454.54545454
    Decimal operator / ( Decimal d2 ) const
    {
        d2.minimizePrecision();

        Decimal d1 = *this;
        d1.expandTo( m_denum.prec() + d2.m_denum.prec() );
        return Decimal( d1.m_num / d2.m_num, m_denum);
    }

    // 1200.00000   % 22.000    = 12.000
    // 1200         % 22        = 12
    // 1200 00000   % 22 000    = 12000
    // 1200 000000  % 22 000    = 10000
    // 1200.00000   % 22.00000  = 12.00000
    // 120000000    % 2200000   = 12 00000

    Decimal operator % ( Decimal d2 ) const
    {
        Decimal d1 = *this;
        adjustPrecisions( d1, d2 );
        d1.m_num %= d2.m_num;
        return d1;
    }


    Decimal& operator += ( Decimal d2 )
    {
        *this = operator+(d2);
        return *this;
    }

    Decimal& operator -= ( Decimal d2 )
    {
        *this = operator-(d2);
        return *this;
    }

    Decimal& operator *= ( Decimal d2 )
    {
        *this = operator*(d2);
        return *this;
    }

    Decimal& operator /= ( Decimal d2 )
    {
        *this = operator/(d2);
        return *this;
    }

    Decimal& operator %= ( Decimal d2 )
    {
        *this = operator%(d2);
        return *this;
    }

    // Decimal operator +   ( int i ) const { return operator+ ( Decimal((int)i, DecimalPrecision(0)) ); }
    // Decimal& operator += ( int i )       { return operator+=( Decimal((int)i, DecimalPrecision(0)) ); }


    #define MARTY_DECIMAL_IMPLEMENT_ARIPHMETICT_OVERLOADS_FOR_INTEGRAL_TYPE( integralType )         \
                                                                                                    \
                Decimal operator +   ( integralType i ) const { return operator+ ( Decimal(i) ); }  \
                Decimal operator -   ( integralType i ) const { return operator- ( Decimal(i) ); }  \
                Decimal operator *   ( integralType i ) const { return operator* ( Decimal(i) ); }  \
                Decimal operator /   ( integralType i ) const { return operator/ ( Decimal(i) ); }  \
                Decimal operator %   ( integralType i ) const { return operator% ( Decimal(i) ); }  \
                                                                                                    \
                Decimal& operator += ( integralType i )       { return operator+=( Decimal(i) ); }  \
                Decimal& operator -= ( integralType i )       { return operator-=( Decimal(i) ); }  \
                Decimal& operator *= ( integralType i )       { return operator*=( Decimal(i) ); }  \
                Decimal& operator /= ( integralType i )       { return operator/=( Decimal(i) ); }  \
                Decimal& operator %= ( integralType i )       { return operator%=( Decimal(i) ); }


    MARTY_DECIMAL_IMPLEMENT_ARIPHMETICT_OVERLOADS_FOR_INTEGRAL_TYPE( int           )
    MARTY_DECIMAL_IMPLEMENT_ARIPHMETICT_OVERLOADS_FOR_INTEGRAL_TYPE( unsigned      )
    MARTY_DECIMAL_IMPLEMENT_ARIPHMETICT_OVERLOADS_FOR_INTEGRAL_TYPE( std::int64_t  )
    MARTY_DECIMAL_IMPLEMENT_ARIPHMETICT_OVERLOADS_FOR_INTEGRAL_TYPE( std::uint64_t )
    MARTY_DECIMAL_IMPLEMENT_ARIPHMETICT_OVERLOADS_FOR_INTEGRAL_TYPE( float         )
    MARTY_DECIMAL_IMPLEMENT_ARIPHMETICT_OVERLOADS_FOR_INTEGRAL_TYPE( double        )



    int compare( Decimal d2 ) const
    {
        if (m_denum.prec()==d2.m_denum.prec())
        {
            return compare(d2.m_num);
        }

        Decimal d1 = *this;
        adjustPrecisions( d1, d2 );
        return d1.compare(d2);
    }

    MARTY_DECIMAL_IMPLEMENT_RELATIONAL_OPERATORS(Decimal)


    static
    Decimal fromRawNumPrec( num_t num, precision_t prec )
    {
        Decimal res;

        res.m_num   = num;
        res.m_denum = DecimalPrecision(prec);

        return res;
    }


protected:


    Decimal( num_t n, DenumeratorType denum) : m_num(n), m_denum(denum)   {}

    static
    void adjustPrecisions( Decimal &d1, Decimal &d2 )
    {
        int cmp = d1.m_denum.compare( d2.m_denum );
        if (cmp==0) return;

        if (cmp<0)
           d1.expandTo(d2.m_denum.prec());
        else
           d2.expandTo(d1.m_denum.prec());
    }

    std::string rtrimZeros( std::string s )
    {
        while( !s.empty() && s.back()=='0' ) s.erase(s.size()-1, 1);
        if ( !s.empty() && (s.back()=='.' || s.back()==',') )
            s.append(1,'0');
        return s;
    }

    template<typename FloatType>
    void fromFloat( FloatType f, precision_t p )
    {
        bool precAuto = (p==0);
        *this = fromString(rtrimZeros(std::to_string(f)));
        if (!precAuto)
            fitTo(p);
    }

    template<typename FloatType>
    void fromFloat( FloatType f, DecimalPrecision p )
    {
        fromFloat( f, p.prec() );
    }

    int compare( num_t n ) const
    {
        if (m_num<n) return -1;
        if (m_num>n) return  1;
        return 0;
    }

    void expandTo( precision_t p )
    {
        denum_t adjust = m_denum.expandTo(p);
        m_num *= adjust;
    }

    void shrinkTo( precision_t p )
    {
        denum_t adjust = m_denum.shrinkTo(p);
        m_num /= adjust;
    }

    void fitTo( precision_t p )
    {
        sdenum_t adjust = m_denum.fitTo(p);
        if (adjust<0)
           m_num /= (denum_t)-adjust;
        else
           m_num *= (denum_t)adjust;
    }

    void minimizePrecision()
    {
        while( ((m_num%10)==0) && (m_denum.prec()>0) )
        {
            m_num /= 10;
            m_denum.decPrec();
        }
    }


    
    //precision_t

    //DecimalPrecision decimalPrecision( )

    num_t               m_num;
    DenumeratorType     m_denum;

}; // class Decimal

//----------------------------------------------------------------------------





//----------------------------------------------------------------------------
#define MARTY_DECIMAL_IMPLEMENT_FRIEND_OVERLOADS_FOR_INTEGRAL_TYPE( integralType )                                          \
                                                                                                                            \
    inline bool operator< ( integralType i, const Decimal &d ) { return Decimal(i) <  d; }                                  \
    inline bool operator<=( integralType i, const Decimal &d ) { return Decimal(i) <= d; }                                  \
    inline bool operator> ( integralType i, const Decimal &d ) { return Decimal(i) >  d; }                                  \
    inline bool operator>=( integralType i, const Decimal &d ) { return Decimal(i) >= d; }                                  \
    inline bool operator==( integralType i, const Decimal &d ) { return Decimal(i) == d; }                                  \
    inline bool operator!=( integralType i, const Decimal &d ) { return Decimal(i) != d; }                                  \
                                                                                                                            \
    inline Decimal operator + ( integralType i, const Decimal &d ) { return Decimal(i).operator+ ( d ); }                   \
    inline Decimal operator - ( integralType i, const Decimal &d ) { return Decimal(i).operator- ( d ); }                   \
    inline Decimal operator * ( integralType i, const Decimal &d ) { return Decimal(i).operator* ( d ); }                   \
    inline Decimal operator / ( integralType i, const Decimal &d ) { return Decimal(i).operator/ ( d ); }                   \
    inline Decimal operator % ( integralType i, const Decimal &d ) { return Decimal(i).operator% ( d ); }

//----------------------------------------------------------------------------




//----------------------------------------------------------------------------
MARTY_DECIMAL_IMPLEMENT_FRIEND_OVERLOADS_FOR_INTEGRAL_TYPE( int           )
MARTY_DECIMAL_IMPLEMENT_FRIEND_OVERLOADS_FOR_INTEGRAL_TYPE( unsigned      )
MARTY_DECIMAL_IMPLEMENT_FRIEND_OVERLOADS_FOR_INTEGRAL_TYPE( std::int64_t  )
MARTY_DECIMAL_IMPLEMENT_FRIEND_OVERLOADS_FOR_INTEGRAL_TYPE( std::uint64_t )
MARTY_DECIMAL_IMPLEMENT_FRIEND_OVERLOADS_FOR_INTEGRAL_TYPE( float         )
MARTY_DECIMAL_IMPLEMENT_FRIEND_OVERLOADS_FOR_INTEGRAL_TYPE( double        )

//----------------------------------------------------------------------------




//----------------------------------------------------------------------------
inline
void swap( Decimal &d1, Decimal &d2 )
{
    d1.swap(d2);
}

//----------------------------------------------------------------------------
inline
std::string toString  ( const Decimal     &d )
{
    Decimal::num_t p1 = d.m_num / d.m_denum.denum();
    Decimal::num_t p2 = d.m_num % d.m_denum.denum();

    std::string res = std::to_string(p1);

    std::size_t prec = d.m_denum.prec();

    if (!prec)
        return res; // No decimal digits after dot

    if (p2<0)
        p2 = -p2;

    std::string strP2 = std::to_string(p2);

    std::size_t leadingZerosNum = 0;
    if (prec>strP2.size())
        leadingZerosNum = prec - strP2.size();

    return res + std::string(1, '.') + std::string(leadingZerosNum, '0') + strP2;
}

//----------------------------------------------------------------------------
template<typename CharType>
inline
int charToDecimalDigit( CharType ch )
{
    if (ch<(CharType)'0') return -1;
    if (ch>(CharType)'9') return -1;
    return (int)(ch - (CharType)'0');
}

//----------------------------------------------------------------------------
template<typename CharType>
inline
bool charIsDecimalSeparator( CharType ch )
{
    if (ch==(CharType)'.') return true;
    if (ch==(CharType)',') return true;
    return false;
}

//----------------------------------------------------------------------------
template<typename CharType>
inline
int charIsSpaceOrTab( CharType ch )
{
    switch((char)ch)
    {
        case ' ' : return true;
        case '\t': return true;
        default  : return false;
    };
}

//----------------------------------------------------------------------------
inline
Decimal     fromString( const std::string &numberStr)
{
    std::string::size_type pos = 0;
    std::string::size_type sz  = numberStr.size();

    bool neg = false;

    while( charIsSpaceOrTab(numberStr[pos]) && pos!=sz ) pos++;
    if (pos==sz) throw std::runtime_error("Decimal fromString - empty string taken as number string");

    if (numberStr[pos]=='+')                        { pos++; }
    else if (numberStr[pos]=='-')                   { pos++; neg = true; }
    else if (charToDecimalDigit(numberStr[pos])>=0) {}
    else throw std::runtime_error("Decimal fromString - invalid character found");

    while( charIsSpaceOrTab(numberStr[pos]) ) pos++;

    std::int64_t  num = 0;
    std::uint32_t precision = 0;

    int dig = charToDecimalDigit(numberStr[pos]);
    while(dig>=0)
    {
        num *= 10;
        num += (std::int64_t)dig;
        pos++;
        dig = charToDecimalDigit(numberStr[pos]);
    }

    if (neg)
        num = -num;

    if (!charIsDecimalSeparator(numberStr[pos]))
    {
        return Decimal( num, DecimalPrecision(0) );
    }

    pos++;

    unsigned prec = 0;

    dig = charToDecimalDigit(numberStr[pos]);
    while( sz != pos && (dig>=0  /* && (d[pos]!=' ' && d[pos]!='\'') */ ) )
    {
        num *= 10;
        num += (std::int64_t)dig;
        pos++;
        dig = charToDecimalDigit(numberStr[pos]);
        prec++;
    }

    return Decimal::fromRawNumPrec( num, prec );

}

//----------------------------------------------------------------------------
inline
std::ostream& operator<<( std::ostream &s, const Decimal &d )
{
    s<<toString(d);
    return s;
}

//----------------------------------------------------------------------------




//----------------------------------------------------------------------------

} // namespace marty


#include <iostream>
#include "marty_decimal.h"

int main()
{
    using std::cout;
    using std::endl;

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

    using marty::Decimal;
    using marty::DecimalPrecision;
    using marty::toString;
    using marty::fromString;

    #define PRINT( var ) cout << #var << ": "<< var << endl;

    Decimal d1_u64_3   = (std::uint64_t)(3)  ; PRINT(d1_u64_3);
    Decimal d1_i64_7   = (std::int64_t )(7)  ; PRINT(d1_i64_7);
    Decimal d1_i64_m10 = (std::int64_t )(-10); PRINT(d1_i64_m10);
    Decimal d1_i64_15_000 = Decimal(15, DecimalPrecision(3)); PRINT(d1_i64_15_000);
    Decimal d1 = fromString("123.010");        PRINT(d1);
    Decimal d2 = fromString("13.10");          PRINT(d2);
    Decimal d1_2_sum = d1 + d2;                PRINT(d1_2_sum);  // 123.010 + 13.10 =  136.11
    Decimal d1_2_raz = d1 - d2;                PRINT(d1_2_raz);  // 123.010 - 13.10 =  109.91
    Decimal d1_2_mul = d1 * d2;                PRINT(d1_2_mul);  // 123.010 * 13.10 = 1611.431
    Decimal d1_2_div = d1 / d2;                PRINT(d1_2_div);  // 123.010 / 13.10 =    9.390076335877862595419847328
    Decimal d1_2_ost = d1 % d2;                PRINT(d1_2_ost);  // 123.010 % 13.10 =    5.11

    auto    d1_2_sum_plus_15_a = d1_2_sum + (std::int64_t )(15); PRINT(d1_2_sum_plus_15_a);
    auto    d1_2_sum_plus_15_b = d1_2_sum + (std::uint64_t)(15); PRINT(d1_2_sum_plus_15_b);
    auto    d1_2_sum_plus_15_c = d1_2_sum + (int          )(15); PRINT(d1_2_sum_plus_15_c);
    auto    d1_2_sum_plus_15_d = d1_2_sum + (unsigned     )(15); PRINT(d1_2_sum_plus_15_d);
    auto    d1_2_sum_plus_15_e = d1_2_sum + (double       )(15); PRINT(d1_2_sum_plus_15_e);
    
    return 0;

}
Маньяк Робокряк колесит по городу
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.