-3

my goal is to turn a double's fraction part into an integer, for example: turn 0.854 into 854 or turn 0.9321 into 9321 (the whole part of the double is always 0)

i was doing it like this, but i dont know how to fill the while's parameters to make it stop when variable x becomes a whole number without a fraction:

double x;
cin >> x;
while(WHAT DO I TYPE HERE TO MAKE IT STOP WHEN X BECOMES A WHOLE NUMBER){
x *= 10;
}

it would be best if i could do it with a loop, but if it is not possible, i am open to other suggestions :)

Gvidas28
  • 53
  • 3
  • 1
    This may be harder than you realize, even impossible. You could get a binary fraction that *never terminates*, even if the decimal fraction looks fine. See [Is floating point math broken?](https://stackoverflow.com/q/588004/10077). – Fred Larson Sep 29 '21 at 19:23
  • 1
    The problem is that repeatedly multiplying the fraction by 10 won't necessarily get you to an integer value. The fraction part of a floating-point value is usually represented as a **binary** value, so you need to repeatedly multiply it by **2** to get it to an integer. – Pete Becker Sep 29 '21 at 19:30
  • 1
    How much of the fractional part do you want to preserve? – Thomas Matthews Sep 29 '21 at 19:58
  • There are some things that needs to be clarified in your question IMHO. *"to turn a double's fraction part into an integer"* 1) Not all the real numbers expressed in decimal format can be exactly converted into a `double`, which usually has a binary representation. 2) You can print out the *exact* value stored in a `double` in decimal representation, but it would take much more than the standard 6 digits, in general. E.g. `std::cout << std::setprecision(60) << 0.1 << '\n';` would output `0.1000000000000000055511151231257827021181583404541015625`. Too big for a standard fixed width integer. – Bob__ Sep 29 '21 at 21:03

4 Answers4

0

That question has no answer in a mathematical/logical sense. You have to read how floating point numbers in computers work, see e.g.

https://en.wikipedia.org/wiki/Floating-point_arithmetic

and understand that they are not decimal point numbers in memory. A floating point number in memory consists of three actual numbers: significant * base^{exponent} and according to IEEE the base used is "2" in basically any modern floating point data, but in even more generality, the base can be anything. Thus, whatever you have in your mind, or even see on your screen as output, is a misleading representation of the data in memory. Your question is, thus, mainly a misconception of how floating point numbers in computers work...

Thus, what you specifically ask for does in general not exist and cannot be done.

However, there may be special application for output formatting or whatever where something like this may make sense -- but then the specific goal must be clearly stated in the question here. And in some of such cases, using a "string-based" approach, as you suggested, will work. But this is not an answer to your generic question and has the high potential to also mislead others in the future.

Actually, one way to make your question obvious and clear is to also specify a fixed desired precision, thus, numbers after the decimal point. Then the answer is quite trivially and correctly:

long int value = fraction * pow(10, precision);

In this scenario you know 100% what your are doing. And if you really like you could subsequently remove zeros from the right side...

int nTrailingZeros = 0;
while (value%10 == 0) {
   value /= 10;
   ++nTrailingZeros;
}

However there is another principle problem on a numerical level: there is no mathematical difference between, e.g., 000003 and just 3, thus in any such application the input 0.000003 will give the same results as 0.0003 or 0.3 etc. This cannot be a desired functionality... it is pretty useless to ask about the *value of the fractional part of a floating point number. But, since we have a known precision`, we can do:

cout << setw(precision-ntrailing) << setfill('0') << value << endl;

which will fill in the eventually missing leading zeros.

See this complete tested test code

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main() {

  double v = 0.0454243252;
  int precision = 14;
  
  long int value = v*pow(10,precision);

  cout << value << endl;
  // 4542432520000

  int nTrailingZeros = 0;
  while (value%10 == 0) {
    value /= 10;
    ++nTrailingZeros;
  }

  cout << value << endl;
  // 454243252

  cout << setw(precision-ntrailing) << setfill('0') << value << endl;
  // 0454243252
}
Ralf Ulrich
  • 1,575
  • 9
  • 25
  • 1
    thank you for explaining everything in detail :) i am a only a beginner, therefore i can only view/write code from a mathematical/logical standpoint right now but your explanation really helped me grasp how everything works behind the scenes – Gvidas28 Oct 01 '21 at 08:09
0

Here is a possible approach:

#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
using namespace std;

int main()
{
    cout << "Enter Number: ";
    double user_input;
    cin >> user_input;

    int user_input_to_int = int(user_input);
    double decimal_value = user_input - user_input_to_int;


    ostringstream oss;
    oss << std::noshowpoint << decimal_value;
    string num_str = oss.str();
    int str_length = num_str.size()-2;

    int multiplier = 1;
    for (int x = 0; x < str_length; x++)
    {
        multiplier *= 10;
    }
    
    cout << "\n";
    cout << "Whole number: " << user_input_to_int << endl;
    cout << "Decimal value: " << decimal_value*multiplier << endl;
}
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
-1

Compare the difference between double and integer part. It is working only if x is less than 2^63.

while (x - long long(x) > 0)
273K
  • 29,503
  • 10
  • 41
  • 64
-2

find 2 real numbers find the fractional part smaller than these numbers