There was once this little function
string format_dollars_for_screen(float d)
{
char ch[50];
sprintf(ch,"%1.2f",d);
return ch;
}
who liked to return -0.00.
I modified it to
string format_dollars_for_screen(float d)
{
char ch[50];
float value;
sprintf(ch,"%1.2f",d);
value = stof(ch);
if(value==0.0f) sprintf(ch,"0.00");
return ch;
}
And it started returning 0.00 as desired. My question is, why doesn't this other solution work?
string format_dollars_for_screen(float d)
{
char ch[50];
float value;
sprintf(ch,"%1.2f",d);
value = stof(ch);
if(value==0.0f) sprintf(ch,"%1.2f", value);
return ch;
}
And/or is there a more efficient way to do this? This is just off the top of my head, so critiques are welcome. =)
Floating point numbers have both, a plus-zero and a minus-zero. They compare equal with the == operator, but produce different results in other arithmetic expressions: 1/+0 == +inf but 1/-0 == -inf.
As for your case, you shall not use floating point numbers for monetary quantities. Instead use integers for counting cents (or other decimal fractions of cents), and format them accordingly:
string format_dollars_for_screen(int cents)
{
bool neg = cents < 0;
if(neg) cents = -cents;
char ch[50];
sprintf(ch, "%s%d.%.2d", "-"+!neg, cents/100, cents%100);
return ch;
}
Related
I am working on this LeetCode problem to take an integer and reverse it, given that the reversed in is within the signed 32-bit range, in which case we should return 0.
and this code is doing just that, even with numbers like 1534236469/-1534236469. Except when it comes to tricky numbers like -2147483648 where its not recognising it as out of range and instead returning 8 and not 0.
I know this is not the cleanest code, but can you help me recognise what I'm missing?
#include<iostream>
#include<limits>
using namespace std;
class Solution {
public:
int reverse(int x) {
int a, r, y;
string num, fnum;
a = abs(x);
try{
while(a != 0){
r = a % 10;
a = a / 10;
num = to_string(r);
fnum = fnum + num;
y = stoi(fnum);
}
} catch(out_of_range& oor){
return 0;
}
if(x==0){
return 0;
} else if (x<0){
return -y;
} else {
return y;
}
}
};
int main(){
Solution mine;
cout << mine.reverse(-2147483648);
}
[...] when it comes to tricky numbers like -2147483648 where its not recognising it as out of range and instead returning 8 and not 0.
That number is "tricky" because it's equal to std::numeric_limits<int>::min() in your environment and given a two's complement representation of type int, it happens that std::abs(-2147483648) == -2147483648.
Next in your (contrived, I must say, there's no need to use a string here) code, the line num = to_string(r); would result in num = "-8", so that the loop would compose a string like "-8-4-6-3-8-4-7-4-1-2".
When applyed to strings like that, stoi doesn't throw an exception, it just stops parsing (you would have noticed it by passing and inspecting its other parameters).
If you want to check if the result is outside the range of an int, you could use locally a wider type (e.g. long long) and check the boundaries after the calculations or keep using int, but compare all the intermediate values with the limits before any calculation.
I want to stringify a fraction of unsigned integers in C++ with variable precision. So 1/3 would be printed as 0.33 using a precision of 2. I know that float and std::ostream::precision could be used for a quick and dirty solution:
std::string stringifyFraction(unsigned numerator,
unsigned denominator,
unsigned precision)
{
std::stringstream output;
output.precision(precision);
output << static_cast<float>(numerator) / denominator;
return output.str();
}
However, this is not good enough because float has limited precision and can't actually represent decimal numbers accurately. What other options do I have? Even a double would fail if I wanted 100 digits or so, or in case of a recurring fraction.
It's always possible to just perform long division to stringify digit-by-digit. Note that the result consists of an integral part and a fractional part. We can get the integral part by simply dividing using the / operator and calling std::to_string. For the rest, we need the following function:
#include <string>
std::string stringifyFraction(const unsigned num,
const unsigned den,
const unsigned precision)
{
constexpr unsigned base = 10;
// prevent division by zero if necessary
if (den == 0) {
return "inf";
}
// integral part can be computed using regular division
std::string result = std::to_string(num / den);
// perform first step of long division
// also cancel early if there is no fractional part
unsigned tmp = num % den;
if (tmp == 0 || precision == 0) {
return result;
}
// reserve characters to avoid unnecessary re-allocation
result.reserve(result.size() + precision + 1);
// fractional part can be computed using long divison
result += '.';
for (size_t i = 0; i < precision; ++i) {
tmp *= base;
char nextDigit = '0' + static_cast<char>(tmp / den);
result.push_back(nextDigit);
tmp %= den;
}
return result;
}
You could easily extend this to work with other bases as well, by just making base a template parameter, but then you couldn't just use std::to_string anymore.
I am trying to better understand how 'big numbers' libraries work, (like GMP for example).
I want to write my own function to Add() / Subtract() / Multiply() / Divide()
The class is traditionally defined ...
std::vector<unsigned char> _numbers; // all the numbers
bool _neg; // positive or negative number
long _decimalPos; // where the decimal point is located
// so 10.5 would be 1
// 10.25 would be 2
// 10 would be 0 for example
First I need to normalise the numbers so I can do
Using 2 numbers
10(x) + 10.25(y) = 20.25
For simplicity, I would make them the same length,
For x:
_numbers = (1,0,0,0) decimal = 2
For y:
_numbers = (1,0,2,5) decimal = 2
And I can then reverse add x to y in a loop
...
// where x is 10.00 and y is 10.25
...
unsigned char carryOver = 0;
int totalLen = x._numbers.size();
for (size_t i = totalLen; i > 1 ; --i )
{
unsigned char sum = x._numbers[i-1] + y._numbers[i-1] + carryOver;
carryOver = 0;
if (sum > _base)
{
sum -= _base;
carryOver = 1;
}
numbers.insert( number.begin(), sum);
}
// any left over?
if (carryOver > 0)
{
numbers.insert( number.begin(), 1 );
}
// decimal pos is the same for this number as x and y
...
The example above will work for adding two positive numbers, but will soon fall over once I need to add a negative number to a positive number.
And this gets more complicated when it comes to subtracting numbers, then even worse for multiplications and divisions.
Can someone suggest some simple functions to Add() / Subtract() / Multiply() / Divide()
I am not trying to re-write / improve libraries, I just want to understand how they work with numbers.
addition and substractions are pretty straightforward
You need to inspect signs and magnitudes of operands and if needed convert the operation to/from +/-. Typical C++ implementation of mine for this is like this:
//---------------------------------------------------------------------------
arbnum arbnum::operator + (const arbnum &x)
{
arbnum c;
// you can skip this if you do not have NaN or Inf support
// this just handles cases like adding inf or NaN or zero
if ( isnan() ) return *this;
if (x.isnan() ) { c.nan(); return c; }
if ( iszero()) { c=x; return c; }
if (x.iszero()) return *this;
if ( isinf() ) { if (x.isinf()) { if (sig==x.sig) return *this;
c.nan(); return c; } return *this; }
if (x.isinf()) { c.inf(); return c; }
// this compares the sign bits if both signs are the same it is addition
if (sig*x.sig>0) { c.add(x,this[0]); c.sig=sig; }
// if not
else{
// compare absolute values (magnitudes)
if (c.geq(this[0],x)) // |this| >= |x| ... return (this-x)
{
c.sub(this[0],x);
c.sig=sig; // use sign of the abs greater operand
}
else { // else return (x-this)
c.sub(x,this[0]);
c.sig=x.sig;
}
}
return c;
}
//---------------------------------------------------------------------------
arbnum arbnum::operator - (const arbnum &x)
{
arbnum c;
if ( isnan() ) return *this;
if (x.isnan() ) { c.nan(); return c; }
if ( iszero()) { c=x; c.sig=-x.sig; return c; }
if (x.iszero()) return *this;
if ( isinf() ) { if (x.isinf()) { if (sig!=x.sig) return *this;
c.nan(); return c; } return *this; }
if (x.isinf()) { c.inf(); c.sig=-x.sig; return c; }
if (x.sig*sig<0) { c.add(x,this[0]); c.sig=sig; }
else{
if (c.geq(this[0],x))
{
c.sub(this[0],x);
c.sig=sig;
}
else {
c.sub(x,this[0]);
c.sig=-x.sig;
}
}
return c;
}
//---------------------------------------------------------------------------
where:
geq is unsigned comparison greater or equal
add is unsigned +
sub is unsigned -
division is a bit more complicated
see:
bignum divisions
approximational bignum divider
For divisions you need to have already implemented things like +,-,*,<<,>> and for some more advanced approaches you need even things like: absolute comparison (you need them for +/- anyway) , sqr, number of used bits usually separate for fractional and integer part.
The most important is the multiplication see Fast bignum square computation because it is core for most division algorithms.
performance
for some hints see BigInteger numbers implementation and performance
text conversion
If your number is in ASCII or in BASE=10^n digits then this is easy but If you use BASE=2^n instead for performance reasons then you need to have fast functions capable of converting between dec and hex strings so you can actually load and print some numbers to/from your class. see:
How do I convert a very long binary number to decimal?
How to convert a gi-normous integer (in string format) to hex format?
Can anybody give an example of c++ code that can easily convert a decimal value to binary and a binary value to decimal please?
Well, your question is really vague, so this answer is the same.
string DecToBin(int number)
{
if ( number == 0 ) return "0";
if ( number == 1 ) return "1";
if ( number % 2 == 0 )
return DecToBin(number / 2) + "0";
else
return DecToBin(number / 2) + "1";
}
int BinToDec(string number)
{
int result = 0, pow = 1;
for ( int i = number.length() - 1; i >= 0; --i, pow <<= 1 )
result += (number[i] - '0') * pow;
return result;
}
You should check for overflow and do input validation of course.
x << 1 == x * 2
Here's a way to convert to binary that uses a more "programming-like" approach rather than a "math-like" approach, for lack of a better description (the two are actually identical though, since this one just replaces divisions by right shifts, modulo by a bitwise and, recursion with a loop. It's kind of another way of thinking about it though, since this makes it obvious you are extracting the individual bits).
string DecToBin2(int number)
{
string result = "";
do
{
if ( (number & 1) == 0 )
result += "0";
else
result += "1";
number >>= 1;
} while ( number );
reverse(result.begin(), result.end());
return result;
}
And here is how to do the conversion on paper:
Decimal to binary
Binary to decimal
strtol will convert a binary string like "011101" to an internal value (which will normally be stored in binary as well, but you don't need to worry much about that). A normal conversion (e.g. operator<< with std:cout) will give the same value in decimal.
//The shortest solution to convert dec to bin in c++
void dec2bin(int a) {
if(a!=0) dec2bin(a/2);
if(a!=0) cout<<a%2;
}
int main() {
int a;
cout<<"Enter the number: "<<endl;
cin>>a;
dec2bin(a);
return 0;
}
I assume you want a string to binary conversion?
template<typename T> T stringTo( const std::string& s )
{
std::istringstream iss(s);
T x;
iss >> x;
return x;
};
template<typename T> inline std::string toString( const T& x )
{
std::ostringstream o;
o << x;
return o.str();
}
use these like this:
int x = 32;
std:string decimal = toString<int>(x);
int y = stringTo<int>(decimal);
How can a hexadecimal floating point constant, as specified in C99, be printed from a array of bytes representing the machine representation of a floating point value? e.g. given
union u_double
{
double dbl;
char data[sizeof(double)];
};
An example hexadecimal floating point constant is a string of the form
0x1.FFFFFEp127f
A syntax specification for this form of literal can be found on the IBM site, and a brief description of the syntax is here on the GCC site.
The printf function can be used to do this on platforms with access to C99 features in the standard library, but I would like to be able to perform the printing in MSVC, which does not support C99, using standard C89 or C++98.
printf manual says:
a,A
(C99; not in SUSv2) For a conversion, the double argument is converted to hexadecimal notation (using the letters abcdef) in the style [-]0xh.hhhhp�d; for A conversion the prefix 0X, the letters ABCDEF, and the exponent separator P is used. There is one hexadecimal digit before the decimal point, and the number of digits after it is equal to the precision. The default precision suffices for an exact representation of the value if an exact representation in base 2 exists and otherwise is sufficiently large to distinguish values of type double. The digit before the decimal point is unspecified for non-normalized numbers, and non-zero but otherwise unspecified for normalized numbers.
You can use frexp() which is in math.h since at least C90 and then do the conversion yourself. Something like this (not tested, not designed to handle boundaries like NaN, infinities, buffer limits, and so on)
void hexfloat(double d, char* ptr)
{
double fract;
int exp = 0;
if (d < 0) {
*ptr++ = '-';
d = -d;
}
fract = frexp(d, &exp);
if (fract == 0.0) {
strcpy(ptr, "0x0.0");
} else {
fract *= 2.0;
--exp;
*ptr++ = '0';
*ptr++ = 'x';
*ptr++ = '1';
fract -= 1.0;
fract *= 16.0;
*ptr++ = '.';
do {
char const hexdigits[] = "0123456789ABCDEF";
*ptr++ = hexdigits[(int)fract]; // truncate
fract -= (int)fract;
fract *= 16;
} while (fract != 0.0);
if (exp != 0) {
sprintf(ptr, "p%d", exp);
} else {
*ptr++ = '\0';
}
}
}
#include <stdint.h>
#include <stdio.h>
int main(void)
{
union { double d; uint64_t u; } value;
value.d = -1.234e-5;
// see http://en.wikipedia.org/wiki/Double_precision
_Bool sign_bit = value.u >> 63;
uint16_t exp_bits = (value.u >> 52) & 0x7FF;
uint64_t frac_bits = value.u & 0xFFFFFFFFFFFFFull;
if(exp_bits == 0)
{
if(frac_bits == 0)
printf("%s0x0p+0\n", sign_bit ? "-" : "");
else puts("subnormal, too lazy to parse");
}
else if(exp_bits == 0x7FF)
puts("infinity or nan, too lazy to parse");
else printf("%s0x1.%llxp%+i\n",
sign_bit ? "-" : "",
(unsigned long long)frac_bits,
(int)exp_bits - 1023);
// check against libc implementation
printf("%a\n", value.d);
}
This might be an "outside the box" answer, but why not convert the double to a string using sprintf, then parse the string for the mantissa and exponent, convert those to
e.g., something like:
char str[256];
long long a, b, c;
sprintf(str, "%e", dbl);
sscanf(str, "%d.%de%d", &a, &b, &c);
printf("0x%x.%xp%x", a, b, c);
I'm sure you'd have to modify the formats for sprintf and sscanf. And you'd never get a first hex digit between A and F. But in general, I think this idea should work. And it's simple.
A better way would be to find an open source library that implements this format for printf (e.g., newlib, uClibc?) and copy what they do.