I needed to convert a fractional part of a number into integer without a comma,
for example I have 3.35 I want to get just 35 part without zero or a comma,
Because I used the modf() function to extract the the fractional part but it gives me a 0.35
if there is any way to do that or to filter the '0.' part I will be very grateful if you show me how with the smaller code possible,
A bit more efficient than converting to a string and back again:
int fractional_part_as_int(double number, int number_of_decimal_places) {
double dummy;
double frac = modf(number,&dummy);
return round(frac*pow(10,number_of_decimal_places));
}
#include <iostream>
#include <cmath>
double round(double r) {
return (r > 0.0) ? std::floor(r + 0.5) : std::ceil(r - 0.5);
}
double floor_to_zero(double f) {
return (f > 0.0) ? std::floor(f) : std::ceil(f);
}
double sign(double s) {
return (s < 0.0) ? -1.0 : 1.0;
}
int frac(double f, int prec) {
return round((f - floor_to_zero(f)) * prec) * sign(f);
}
int main() {
double a = 1.2345;
double b = -34.567;
std::cout << frac(a, 100) << " " << frac(b, 100) << std::endl; // 23 57
}
another solution
int precision= 100;
double number = 3.35;
int f = floor(xx);
double temp = ( f - number ) * -1;
int fractional_part = temp * precision;
IF you need it as a string, a quite easy C style solution would be (should work for variable number of decimal places):
double yourNumber = 0.35f;
char buffer[32];
snprintf(buffer, 32, "%g", yourNumber);
strtok(buffer, "."); // Here we would get the part before . , should still check
char* fraction = strtok(NULL, ".");
int fractionAsInt = atoi(fraction);
This example lacks error handling in case of a bad string and is not feasible if you just need a fixed number of decimal places, since the arithmetic approaches work better there.
Something like this should work:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
static int get_frac(double value, unsigned short precision)
{
return (int)((value - (long)value) * pow(10, precision));
}
static int get_frac_no_trailing_zeros(double value, unsigned short precision)
{
int v = get_frac(value, precision);
while (v % 10 == 0)
v /= 10;
return v;
}
int main(int argc, char *argv[])
{
double v;
v = 123.4564;
printf("%.4f = %d\n", v, get_frac(v, 2));
printf("%.4f = %d\n", v, get_frac(v, 4));
printf("%.4f = %d\n", v, get_frac(v, 6));
printf("%.4f = %d\n", v, get_frac_no_trailing_zeros(v, 6));
return EXIT_SUCCESS;
}
You may also want to either avoid calling pow by having a user supply a number in a power of 10 in a first place, or use a lookup table.
Using some stl magic, here is the sample code:
typedef std::pair<int, int> SplitFloat;
SplitFloat Split(float value, int precision)
{
// Get integer part.
float left = std::floor(value);
// Get decimal part.
float right = (value - left) * float(std::pow(10, precision));
return SplitFloat(left, right);
}
It can be improved, but is pretty straightforward.
I just did something close to what you are trying to do, though I'm still pretty new. None the less, maybe this will help someone in the future as I landed here looking for results for my problem.
The first step is making sure that the variable that contains 3.35 is a double, but that's probably obvious.
Next, create a variable that is only an integer and set it's value equal to the value of the double. It will then only contain the whole number.
Then subtract the whole number (int) from the double. You will be left with the fraction/decimal value. From there, just multiply by 100.
Beyond the 100ths decimal value, you would have to do a little more configuring obviously, but it should be fairly simple to do with an if statement. If the decimal value is greater than .99, multiply 1000 instead etc..
Here's how I would do it.
#include <sstream>
#include <string>
int main()
{
double d = yourDesiredNumber; //this is your number
std::ostringstream out;
out << setprecision(yourDesiredPrecision) << std::fixed
<< std::showpoint << d;
std::istringstream in(out.str());
std::string wholePart; //you won't need this.
int fractionalPart;
std::getline(in, wholePart, '.');
in >> fractionalPart;
//now fractionalPart contains your desired value.
}
I'm pretty sure that instead of two different istringstream and ostringstream objects you could have gotten away with just one stringstream object, but I am not sure about the details (never used that class) so I didn't use it in the example.
Related
I am on week 3 of C++ & I am so lost. I need to write a program with function decimal - that will return the decimal part of any non negative decimal number sent to it as input. Needs to be clear that it needs to return a double - parameters set at double.
we haven't learned about function decimal yet nor type coercion and trying to teach myself isn't going well.
Check the following example. You can try something like this that is pretty simple.
double num = 23.345;
int intpart = (int)num;
double decpart = num - intpart;
printf("Num = %f, intpart = %d, decpart = %f\n", num, intpart, decpart);
You can use string conversions:
#include <algorithm>
#include <iostream>
#include <string>
int main() {
float input = 12.123456;
std::string ip = std::to_string(input);
ip.erase(ip.begin(), --std::find(ip.begin(), ip.end(), '.'));
ip.front() = '0';
std::cout << ip;
return 0;
}
Another way would be simply substracting the floor of the number from itself...
#include <iostream>
#include <cmath>
int main() {
float input = 12.12;
std::cout << (input - std::floor(input));
return 0;
}
I'm not quit sure that I'm fully understand your question.
Are you having an hard time implementing this function?
If so - think about subtracting the integral part of the number from it, and in that way you will remain with the decimal part only.
Something like: (pseudo code)
double a = 10.85
int b = int(a)
return a - b
Think about the math.
A decimal number is of form a.b where a is the integral part and b the fractional part.
Suppose your input is N (= 1.234) then to extract say frac = .234 you just need to do is
frac = N - floor(N); remember floor(N) is of 1.000.
I think this is of help implement the code.
An example:
#include <iostream>
#include <cmath>
int main() {
float input;
std::cin >> input;
std::cout << (input - std::floor(input));
return 0;
}
or
as a function
#include <cmath>
double decimal(const double &N){
return (N - std::floor(N));
}
Is there a direct function to set the decimal of number. For example I got 3.14341
and my parameter is 2, so I get 3.14. There is a function setprecision but it only prints the result. Also, I made an algorithm like this:
std::string fixPrecision(std::string const& value, int digits)
{
std::string num = value;
float temp = std::stof(num);
float fractpart, intpart;
fractpart = modf(temp, &intpart);
int a = (int)(fractpart * pow(10,digits));
double last = intpart + a*(pow(0.1 , digits));
return std::to_string(last);
}
It works well. I get what I want but I have to convert it to string so the result is 123.120000 instead of 123.12.
I could sure use some help here. Thanks in advance.
Edit: It is not a duplicate question because my function needs to take integer and return numbers with string format. Thanks again.
Fool of me. The answer is as simple as this. I did a lot of things needlessly...
std::string fixPrecision(std::string const& value, int digits)
{
auto pos = value.find(".");
if(pos != std::string::npos)
return value.substr(0, pos+digits+1);
return value;
}
not exactly, but you can set the precision using std::setprecision
define a method:
void printWithPrecision(const double value, unsigned decimalPlaces)
{
std::cout << "A Double with " << decimalPlaces <<" decimal places: "<<std::setprecision(decimalPlaces) << value << std::endl;
}
and call it like:
double d = 7987.12354689765416;
for (auto x = 0; x<10; x++)
{
printWithPrecision(d, x);
}
dont forget to include the input-output-manipulator:
#include <iomanip>
i have the following problem:
customer want to present double type to a string by an optimal way. it need to be converted to string and showed on a form(sms, table and other).
100000000.949999 needs to be converted in 100000000.950;
10.000000001 -> 10.0;
100000000000000.19292 -> 1e+14;
1000.123456789 -> 1000.123;
0.00001 -> 0.0;
The code for converting is a performance critical, it means that no std::stringstream + setprecision() should be used.
It will be great to implement params 'precision' as argument of my toStringNew() function, but this improvements may critically affects all our system, and we are planning implement it in the next release.
But this problem is actual now.
I wrote the following code:
inline bool toStringNew(std::string& str, double const& value)
{
static const char *zero_double_str = "0.0";
static const double zero_double_limit = 0.001;
static const int max_double_prec_symbol = 13;
static const int max_fract_num = 3;
static const int max_fract_mul = pow(10, max_fract_num);
str.clear();
//get digits of integer part
double fabs_value = fabs(value);
int64_t len = log10(fabs_value);
//Round 2 zero
if(len <= 0) //it means that only fraction part is present
{
if(fabs_value < zero_double_limit)
{
str = zero_double_str;
return true;
}
//use default
return boost::spirit::karma::generate(std::back_inserter(str), value);
}
else if(len > max_double_prec_symbol) //default
{
return boost::spirit::karma::generate(std::back_inserter(str), value);
}
//cast to integer
int64_t i = static_cast<int64_t>(value);
//cast fract to integer
int64_t fract_i = static_cast<int64_t>(round((value - i)* max_fract_mul));
//reserve string memory
size_t str_len = len + 1 + max_fract_num + (value > 0 ? 0 : 1) + 1;
str.reserve(str_len);
//convert integer
boost::spirit::karma::generate(std::back_inserter(str), i);
str+='.';
//convert fract
if(fract_i > 0)
{
str+='.';
int64_t fract_i_len = log10(fract_i);
//fill zero before: 0.001 -> 1 -> 001
while(++fract_i_len < max_fract_num)
{
str += '0';
}
//remove zero after: 010 -> 01
while(!(fract_i % 10))
{
fract_i = fract_i / 10;
}
boost::spirit::karma::generate(std::back_inserter(str), fract_i);
}
boost::spirit::karma::generate(std::back_inserter(str), fract_i);
return true;
}
This works at 1,5 times faster than boost::spirit::karma::generate() for double type.
Can you give me some advices how to satisfy my customer?
I would look at the C++ String Toolkit Library. I have used it for parsing and number conversion and it has shown to be very fast.
#include <cmath>
#include <strtk.hpp>
#include <iostream>
using namespace std;
int main ( int argc, char **argv )
{
double pi = M_PI;
std::cout << strtk::type_to_string<double>( pi ) << std::endl;
return 0;
}
If performance is critical maybe use snprintf. It will be better than your home grown solution and also I think it will perform better. Using the * format specifier you can also make the precision an argument.
Suppose I have a float. I would like to round it to a certain number of significant digits.
In my case n=6.
So say float was f=1.23456999;
round(f,6) would give 1.23457
f=123456.0001 would give 123456
Anybody know such a routine ?
Here it works on website: http://ostermiller.org/calc/significant_figures.html
Multiply the number by a suitable scaling factor to move all significant digits to the left of the decimal point. Then round and finally reverse the operation:
#include <math.h>
double round_to_digits(double value, int digits)
{
if (value == 0.0) // otherwise it will return 'nan' due to the log10() of zero
return 0.0;
double factor = pow(10.0, digits - ceil(log10(fabs(value))));
return round(value * factor) / factor;
}
Tested: http://ideone.com/fH5ebt
Buts as #PascalCuoq pointed out: the rounded value may not exactly representable as a floating point value.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *Round(float f, int d)
{
char buf[16];
sprintf(buf, "%.*g", d, f);
return strdup(buf);
}
int main(void)
{
char *r = Round(1.23456999, 6);
printf("%s\n", r);
free(r);
}
Output is:
1.23457
Something like this should work:
double round_to_n_digits(double x, int n)
{
double scale = pow(10.0, ceil(log10(fabs(x))) + n);
return round(x * scale) / scale;
}
Alternatively you could just use sprintf/atof to convert to a string and back again:
double round_to_n_digits(double x, int n)
{
char buff[32];
sprintf(buff, "%.*g", n, x);
return atof(buff);
}
Test code for both of the above functions: http://ideone.com/oMzQZZ
Note that in some cases incorrect rounding may be observed, e.g. as pointed out by #clearScreen in the comments below, 13127.15 is rounded to 13127.1 instead of
13127.2.
This should work (except the noise given by floating point precision):
#include <stdio.h>
#include <math.h>
double dround(double a, int ndigits);
double dround(double a, int ndigits) {
int exp_base10 = round(log10(a));
double man_base10 = a*pow(10.0,-exp_base10);
double factor = pow(10.0,-ndigits+1);
double truncated_man_base10 = man_base10 - fmod(man_base10,factor);
double rounded_remainder = fmod(man_base10,factor)/factor;
rounded_remainder = rounded_remainder > 0.5 ? 1.0*factor : 0.0;
return (truncated_man_base10 + rounded_remainder)*pow(10.0,exp_base10) ;
}
int main() {
double a = 1.23456999;
double b = 123456.0001;
printf("%12.12f\n",dround(a,6));
printf("%12.12f\n",dround(b,6));
return 0;
}
If you want to print a float to a string use simple sprintf(). For outputting it just to the console you can use printf():
printf("My float is %.6f", myfloat);
This will output your float with 6 decimal places.
Print to 16 significant digit.
double x = -1932970.8299999994;
char buff[100];
snprintf(buff, sizeof(buff), "%.16g", x);
std::string buffAsStdStr = buff;
std::cout << std::endl << buffAsStdStr ;
What are the different techniques used to convert float type of data to integer in C++?
#include <iostream>
using namespace std;
struct database {
int id, age;
float salary;
};
int main() {
struct database employee;
employee.id = 1;
employee.age = 23;
employee.salary = 45678.90;
/*
How can i print this value as an integer
(with out changing the salary data type in the declaration part) ?
*/
cout << endl << employee.id << endl << employee.
age << endl << employee.salary << endl;
return 0;
}
What you are looking for is 'type casting'. typecasting (putting the type you know you want in brackets) tells the compiler you know what you are doing and are cool with it. The old way that is inherited from C is as follows.
float var_a = 9.99;
int var_b = (int)var_a;
If you had only tried to write
int var_b = var_a;
You would have got a warning that you can't implicitly (automatically) convert a float to an int, as you lose the decimal.
This is referred to as the old way as C++ offers a superior alternative, 'static cast'; this provides a much safer way of converting from one type to another. The equivalent method would be (and the way you should do it)
float var_x = 9.99;
int var_y = static_cast<int>(var_x);
This method may look a bit more long winded, but it provides much better handling for situations such as accidentally requesting a 'static cast' on a type that cannot be converted. For more information on the why you should be using static cast, see this question.
Normal way is to:
float f = 3.4;
int n = static_cast<int>(f);
Size of some float types may exceed the size of int.
This example shows a safe conversion of any float type to int using the int safeFloatToInt(const FloatType &num); function:
#include <iostream>
#include <limits>
using namespace std;
template <class FloatType>
int safeFloatToInt(const FloatType &num) {
//check if float fits into integer
if ( numeric_limits<int>::digits < numeric_limits<FloatType>::digits) {
// check if float is smaller than max int
if( (num < static_cast<FloatType>( numeric_limits<int>::max())) &&
(num > static_cast<FloatType>( numeric_limits<int>::min())) ) {
return static_cast<int>(num); //safe to cast
} else {
cerr << "Unsafe conversion of value:" << num << endl;
//NaN is not defined for int return the largest int value
return numeric_limits<int>::max();
}
} else {
//It is safe to cast
return static_cast<int>(num);
}
}
int main(){
double a=2251799813685240.0;
float b=43.0;
double c=23333.0;
//unsafe cast
cout << safeFloatToInt(a) << endl;
cout << safeFloatToInt(b) << endl;
cout << safeFloatToInt(c) << endl;
return 0;
}
Result:
Unsafe conversion of value:2.2518e+15
2147483647
43
23333
For most cases (long for floats, long long for double and long double):
long a{ std::lround(1.5f) }; //2l
long long b{ std::llround(std::floor(1.5)) }; //1ll
Check out the boost NumericConversion library. It will allow to explicitly control how you want to deal with issues like overflow handling and truncation.
I believe you can do this using a cast:
float f_val = 3.6f;
int i_val = (int) f_val;
the easiest technique is to just assign float to int, for example:
int i;
float f;
f = 34.0098;
i = f;
this will truncate everything behind floating point or you can round your float number before.
One thing I want to add. Sometimes, there can be precision loss. You may want to add some epsilon value first before converting. Not sure why that works... but it work.
int someint = (somedouble+epsilon);
This is one way to convert IEEE 754 float to 32-bit integer if you can't use floating point operations. It has also a scaler functionality to include more digits to the result. Useful values for scaler are 1, 10 and 100.
#define EXPONENT_LENGTH 8
#define MANTISSA_LENGTH 23
// to convert float to int without floating point operations
int ownFloatToInt(int floatBits, int scaler) {
int sign = (floatBits >> (EXPONENT_LENGTH + MANTISSA_LENGTH)) & 1;
int exponent = (floatBits >> MANTISSA_LENGTH) & ((1 << EXPONENT_LENGTH) - 1);
int mantissa = (floatBits & ((1 << MANTISSA_LENGTH) - 1)) | (1 << MANTISSA_LENGTH);
int result = mantissa * scaler; // possible overflow
exponent -= ((1 << (EXPONENT_LENGTH - 1)) - 1); // exponent bias
exponent -= MANTISSA_LENGTH; // modify exponent for shifting the mantissa
if (exponent <= -(int)sizeof(result) * 8) {
return 0; // underflow
}
if (exponent > 0) {
result <<= exponent; // possible overflow
} else {
result >>= -exponent;
}
if (sign) result = -result; // handle sign
return result;
}