1

I need to build a function that takes uin64_t (SATOSHI) and spits a string with BTC value. I was told to do it without any division/floats, so plain string operation should be involved. This is because if i go Satoshi/1BTC i will end up with a good value but will not be able to convert it into a string properly (due to rounding)

Can't think of a way how to do it, knowing that:

uin64_t uiSatoshi = 1033468;
uint64_t uiOneBTC = 100000000;
std::string strBTC = "";

How to construct the strBTC out of UiSatoshi, knowing that BTC has 8 decimals.

Tried:

// SATOSHI TO STRING (for exchange)  
    int iSatoshi = 1033468;
    double dVal = (double)iSatoshi / (double)100000000;


    std::ostringstream out;
    out << std::setprecision(8) << dVal;
    std::string strOutput = out.str();

    printf("WRONG: %f\n", dVal);
    printf("TEST: %s\n", strOutput.data());

WRONG: 0.010335 TEST: 0.01033468

But it failed when the value of uiSatoshi is = 101033468 As the results are round: TEST: 1.0103347

And i want to avoid doing floating point operations, just make a string out of the integer i have, add leading zeroes and place dot where needed.

Update: Answer posted here: C++ printf Rounding?

Community
  • 1
  • 1
PeeS
  • 1,164
  • 3
  • 20
  • 43

1 Answers1

1

A simple conversion routine could be as follows:

#include <iostream>
#include <string>

using namespace std;

string to_btc(uint64_t sat) {
  auto s = to_string(sat);

  if (s.length() < 8) {
    // Prefix with 0s
    s.insert(0, (8 - s.length()), '0');
    s.insert(0, "0.", 2);
  } else if (s.length() == 8) {
    s.insert(0, "0.", 2);
  } else {
    // Insert a '.' in the right place
    s.insert(s.length() - 8, 1, '.');
  }
  return s;
}

int main ()
{
  cout << to_btc(10346834567ULL) << endl;
  cout << to_btc(1034683456ULL) << endl;
  cout << to_btc(103468345) << endl;
  cout << to_btc(10346834) << endl;
  cout << to_btc(1034683) << endl;
  cout << to_btc(10368) << endl;
  cout << to_btc(1038) << endl;
  cout << to_btc(132) << endl;
  cout << to_btc(18) << endl;
  cout << to_btc(1) << endl;
  cout << to_btc(0) << endl;
}

No need for floats, I'm not saying this is complete and ready for production, but I'm sure you can test it thoroughly to check it gives what you expect. Could it be optimized - possibly, but I'll leave that as an exercise...

Nim
  • 33,299
  • 2
  • 62
  • 101