应用场景
1、在处理港交所中的Decimal类型时,需要将Decimal类型的字段除以pow(10, 8),还原为Double类型。
2、当传输给OCG时还要将Double类型还原为Decimal类型。
代码实现
我们把Double转换为String,经过处理,然后在转换为Decimal。这样可以避免计算中的精度丢失。
参考比特币中的处理
static const int64 HKCOIN = 100000000;
std::string FormatMoney(const int64& n)
{
// Note: not using straight sprintf here because we do NOT want
// localized number formatting.
int64_t n_abs = (n > 0 ? n : -n);
int64_t quotient = n_abs/HKCOIN;
int64_t remainder = n_abs%HKCOIN;
std::string str = strprintf("%d.%08d", quotient, remainder);
// Right-trim excess zeros before the decimal point:
int nTrim = 0;
for (int i = (int)str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
++nTrim;
if (nTrim)
str.erase(str.size()-nTrim, nTrim);
if (n < 0)
str.insert((unsigned int)0, 1, '-');
return str;
}
bool ParseMoney(const std::string& str, int64& nRet)
{
return ParseMoney(str.c_str(), nRet);
}
/**
* Tests if the given character is a decimal digit.
* @param[in] c character to test
* @return true if the argument is a decimal digit; otherwise false.
*/
constexpr bool IsDigit(char c)
{
return c >= '0' && c <= '9';
}
/**
* Tests if the given character is a whitespace character. The whitespace characters
* are: space, form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal
* tab ('\t'), and vertical tab ('\v').
*
* This function is locale independent. Under the C locale this function gives the
* same result as std::isspace.
*
* @param[in] c character to test
* @return true if the argument is a whitespace character; otherwise false
*/
constexpr inline bool IsSpace(char c) noexcept {
return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
}
bool ParseMoney(const char* pszIn, int64& nRet)
{
std::string strWhole;
int64_t nUnits = 0;
const char* p = pszIn;
while (IsSpace(*p))
p++;
for (; *p; p++)
{
if (*p == '.')
{
p++;
int64_t nMult = HKCOIN / 10;
while (isdigit(*p) && (nMult > 0))
{
nUnits += nMult * (*p++ - '0');
nMult /= 10;
}
break;
}
if (IsSpace(*p))
break;
if (!isdigit(*p))
return false;
strWhole.insert(strWhole.end(), *p);
}
for (; *p; p++)
if (!IsSpace(*p))
return false;
if (strWhole.size() > 10) // guard against 63 bit overflow
return false;
if (nUnits < 0 || nUnits > HKCOIN)
return false;
int64_t nWhole = strtoll(strWhole.c_str(), nullptr, 10);
int64 nValue = nWhole*COIN + nUnits;
nRet = nValue;
return true;
}
int main(int argc,char* argv[]) {
string s = FormatMoney(1000000006);
std::cout << s << endl;
int64 n = 0;
bool b = ParseMoney("10000.03100012", n);
std::cout << n << endl;
return 0;
}