Transform rational numbers to integers - c++

How can I transform rational numbers like 1.24234 or 45.314 into integers like 124234 or 45314 also getting the number of decimal digits?

Convert to a string
Find the position of the decimal point.
Subtract that from the length of the above string, for the number of decimals.
Then take the point out of the string.

int i=0;
float a = 1.24234;
for(i; i<20; i++){
float b=pow(10,i);
if((a*b)%10==0)
break;
}
int c = pow(10,i-1);
int result = a*c;
I think this code will help you.

If your number is W.D (Whole.Decimal)
To get W just do (int)W.D.
To get D you can do W.D - (int) W.D
Now you have your whole number and your decimal point separated. To figure out your x10 multiplier on your W keep dividing D by 10 until you get a result that is less than 10.
Now: WxN+D
(where N is the number of times you divided by 10)
Note: I didn't write the code as an example, because I feel this may be a homework assignment. Also, if you are using very long (ie: precise floating points) this won't hold, and could likely overflow. Check your bounds before implementing something like this.

Related

Getting the decimal part of a double variable and convert it to char array?

I'm doing a little library to be able to do operations with really big numbers, and now I'm trying to implement the decimal part of them.
To generate said numbers, I need a double number to translate it into a char array. The integer part is done, but the decimal part is what is making me struggle.
Take a look at this program:
double a = 123.123456;
double dec = a - int(a);
while (dec) {
dec *= 10;
cout << int(dec); // Here it just outputs the decimal digit for the sake of simplicity.
dec -= int(dec);
}
At first, I thought "Okay, this will do it", but the output, instead of being 123456 it is 123456000000004451067070476710796356201171875.
I'm almost sure that this is because of the precision of the double numbers, but I really want to get the 123456 part.
This problem is even more difficult when I add more decimals to the first number, because the "real" digits intersect with the "non-real" ones.
What should I do?
EDIT:
When the double number has a decimal part of 0 (like 123. or 123.0 or 123.00000000), there is no garbage digits.

How can I find the amount of numbers in double?

Let's say I have an input 1.251564.
How can I find how many elements are after "." to have an output as follows:
int numFloating;
// code to go here that leads to
// numFloating == 6
p.s. Sorry for not providing any code, I just have no idea how that should be implemented :(
Thanks for your answers!
Let us consider your number, 1.251564. When you store this in a double, it is stored in the binary IEEE754 format. And you might find that the number is not representable. So, let us check for this number. The closest representable double is:
1.25156 39999 99999 89880 45035 73046 53152 82344 81811 52343 75
This probably comes as something of a surprise to you. There are 52 decimal digits following the decimal point.
The lesson that you need to take away from this is that if you want to ask questions about decimal representations, you need to use a decimal data type rather than double. Once you can actually represent the value exactly, then you will be able to reason about it in a manner that matches your expectations.
Simplest way would be to store it in string.
std::string str("1.1234");
size_t length = str.length();
size_t found = str.find('.', 0 );
size_t count = length-found-1;
int finallyGotTheCount = static_cast<int>(count);
This won't end up well. The problem is that sometimes there are float errors when representing numbers in binary (which is what your computer does).
For example, when adding 1 / 3 + 1 / 3 + 1 / 3 you might get 0.999999... and the number of decimal places varies greatly.
ravi already provided a good way to calculate it, so I'll provide a different one:
double number = 0; // should be equal to the number you want to check
int numFloating = 0;
while ((double)(int)number != number){
number *= 10;
numFloating++;
}
number is a double variable that holds the number you want to check for decimal places.
If you have a fractional number. Lets say .1234
Repeatedly multiply by 10 and throw away the integer portion of the number until you get zero. The number of steps will be the number of decimals. e.g:
.1234 * 10 = 1.234
.234 * 10 = 2.34
.34 * 10 = 3.4
.4 * 10 = 4.0
Problems will however occur when you have a number that is "floating" like 1.199999999.
int numFloating = 0;
double orgin = 1.251564;
double value = orgin - floor(orgin);
while(value == 0)
{
value *= 10;
value = value - floor(value);
numFloating ++;
}
By using this code sometimes answer is wrong. exp: zero in floating point is equal to (2^31)-1.
Obviously output depends on how it realy stored.

Losing Double Precision when multiplying by multiple of 10 [duplicate]

This question already has answers here:
Precision loss with double C++
(4 answers)
Closed 9 years ago.
So I have the following code
int main(){
double d;
cin>>d;
while(d!=0.00)
{
cout<<d<<endl;
double m = 100*d;
int n = m;
cout<<n<<endl;
cin>>d;
}
return 0;}
When I enter the input 20.40 for d the value of n comes out to be 2039 instead of 2040.
I tried replacing int n = m with int n = (int) m but the result was the same.
Is there any way to fix this. Thanks in advance.
Your code truncates m but you need rounding. Include cmath and use int n = round(m).
Decimal values can, in general, not be represented exactly using binary floating points like double. Thus, the value 20.40 is represented as an approximation which can be used to restore the original value (20.4; the precision cannot be retained), e.g., when formatting the value. Doing computations with these approximated values will typically amplify the error.
As already mentioned in one of the comments, the relevant reference is the paper "What Every Computer Scientist Should Know About Floating-Point Arithmetic". One potential way out of your trouble is to use decimal floating points which are, however, not yet part of the C++ standard.
Single and double presicion floating point numbers are not stored the same way as integers, so whole numbers (e.g. 5, 10) may actually look like long decimals (e.g. 4.9999001, 10.000000001). When you cast to an int, all it does is truncate the whole number. So, if the number is currently represented as 4.999999999, casting it to an int will give you 4. std::round will provide you with a better result most of the time (if the number is 4.6 and you just want the whole number portion, round will not work well). The bigger question is then: what are you hoping to accomplish by casting a double to an int?
In general, when dealing with floating point numbers, you will want to use some epsilon value that is your minimum significant digits. So if you wanted to compare 4.9999999 to 5, you would do (pseudo-code): if abs(5 - 4.9999999) < epsilon, return 5.
Example
int main()
{
double d;
std::cin >> d;
while (std::fabs(d - 0.0) > DBL_EPSILON)
{
std::cout << d << std::endl;
double m = 100 * d;
int n = static_cast<int>(m);
if (std::fabs(static_cast<double>(n) - m) > DBL_EPSILON)
{
n++;
}
std::cout << n << std::endl;
std::cin >> d;
}
return 0;
}
Casting double to int truncates value so 20.40 is probably 20.399999 * 100 is 2039.99 because double is not base 10. You can use round() function that will not truncate but will get you nearest int.
int n = round(m);
Floating point numbers can't exactly represent all decimal numbers, sometimes an approximation is used. In your example the closest possible exact number is 20.39999999999999857891452847979962825775146484375. See IEEE-754 Analysis for a quick way to see exact values.
You can use rounding, but presumably you're really looking for the first two digits truncated. Just add a really small value, e.g. 0.0000000001 before or after you multiply.

Weird Rounding Occurs in C++ Function

I am writing a function in c++ that is supposed to find the largest single digit in the number passed (inputValue). For example, the answer for .345 is 5. However, after a while, the program is changing the inputValue to something along the lines of .3449 (and the largest digit is then set to 9). I have no idea why this is happening. Any help to resolve this problem would be greatly appreciated.
This is the function in my .hpp file
void LargeInput(const double inputValue)
//Function to find the largest value of the input
{
int tempMax = 0,//Value that the temporary max number is in loop
digit = 0,//Value of numbers after the decimal place
test = 0,
powerOten = 10;//Number multiplied by so that the next digit can be checked
double number = inputValue;//A variable that can be changed in the function
cout << "The number is still " << number << endl;
for (int k = 1; k <= 6; k++)
{
test = (number*powerOten);
cout << "test: " << test << endl;
digit = test % 10;
cout << (static_cast<int>(number*powerOten)) << endl;
if (tempMax < digit)
tempMax = digit;
powerOten *= 10;
}
return;
}
You cannot represent real numbers (doubles) precisely in a computer - they need to be approximated. If you change your function to work on longs or ints there won't be any inaccuracies. That seems natural enough for the context of your question, you're just looking at the digits and not the number, so .345 can be 345 and get the same result.
Try this:
int get_largest_digit(int n) {
int largest = 0;
while (n > 0) {
int x = n % 10;
if (x > largest) largest = x;
n /= 10;
}
return largest;
}
This is because the fractional component of real numbers is in the form of 1/2^n. As a result you can get values very close to what you want but you can never achieve exact values like 1/3.
It's common to instead use integers and have a conversion (like 1000 = 1) so if you had the number 1333 you would do printf("%d.%d", 1333/1000, 1333 % 1000) to print out 1.333.
By the way the first sentence is a simplification of how floating point numbers are actually represented. For more information check out; http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding
This is how floating point number work, unfortunately. The core of the problem is that there are an infinite number of floating point numbers. More specifically, there are an infinite number of values between 0.1 and 0.2 and there are an infinite number of values between 0.01 and 0.02. Computers, however, have a finite number of bits to represent a floating point number (64 bits for a double precision number). Therefore, most floating point numbers have to be approximated. After any floating point operation, the processor has to round the result to a value it can represent in 64 bits.
Another property of floating point numbers is that as number get bigger they get less and less precise. This is because the same 64 bits have to be able to represent very big numbers (1,000,000,000) and very small numbers (0.000,000,000,001). Therefore, the rounding error gets larger when working with bigger numbers.
The other issue here is that you are converting from floating point to integer. This introduces even more rounding error. It appears that when (0.345 * 10000) is converted to an integer, the result is closer to 3449 than 3450.
I suggest you don't convert your numbers to integers. Write your program in terms of floating point numbers. You can't use the modulus (%) operator on floating point numbers to get a value for digit. Instead use the fmod function in the C math library (cmath.h).
As other answers have indicated, binary floating-point is incapable of representing most decimal numbers exactly. Therefore, you must reconsider your problem statement. Some alternatives are:
The number is passed as a double (specifically, a 64-bit IEEE-754 binary floating-point value), and you wish to find the largest digit in the decimal representation of the exact value passed. In this case, the solution suggested by user millimoose will work (provided the asprintf or snprintf function used is of good quality, so that it does not incur rounding errors that prevent it from producing correctly rounded output).
The number is passed as a double but is intended to represent a number that is exactly representable as a decimal numeral with a known number of digits. In this case, the solution suggested by user millimoose again works, with the format specification altered to convert the double to decimal with the desired number of digits (e.g., instead of “%.64f”, you could use “%.6f”).
The function is changed to pass the number in another way, such as with decimal floating-point, as a scaled integer, or as a string containing a decimal numeral.
Once you have clarified the problem statement, it may be interesting to consider how to solve it with floating-point arithmetic, rather than calling library functions for formatted output. This is likely to have pedagogical value (and incidentally might produce a solution that is computationally more efficient than calling a library function).

Why do simple doubles like 1.82 end up being 1.819999999645634565360? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why does Visual Studio 2008 tell me .9 - .8999999999999995 = 0.00000000000000055511151231257827?
c++
Hey so i'm making a function to return the number of a digits in a number data type given, but i'm having some trouble with doubles.
I figure out how many digits are in it by multiplying it by like 10 billion and then taking away digits 1 by 1 until the double ends up being 0. however when putting in a double of value say .7904 i never exit the function as it keeps taking away digits which never end up being 0 as the resut of .7904 ends up being 7,903,999,988 and not 7,904,000,000.
How can i solve this problem?? Thanks =) ! oh and any other feed back on my code is WELCOME!
here's the code of my function:
/////////////////////// Numb_Digits() ////////////////////////////////////////////////////
enum{DECIMALS = 10, WHOLE_NUMBS = 20, ALL = 30};
template<typename T>
unsigned long int Numb_Digits(T numb, int scope)
{
unsigned long int length= 0;
switch(scope){
case DECIMALS: numb-= (int)numb; numb*=10000000000; // 10 bil (10 zeros)
for(; numb != 0; length++)
numb-=((int)(numb/pow((double)10, (double)(9-length))))* pow((double)10, (double)(9-length)); break;
case WHOLE_NUMBS: numb= (int)numb; numb*=10000000000;
for(; numb != 0; length++)
numb-=((int)(numb/pow((double)10, (double)(9-length))))* pow((double)10, (double)(9-length)); break;
case ALL: numb = numb; numb*=10000000000;
for(; numb != 0; length++)
numb-=((int)(numb/pow((double)10, (double)(9-length))))* pow((double)10, (double)(9-length)); break;
default: break;}
return length;
};
int main()
{
double test = 345.6457;
cout << Numb_Digits(test, ALL) << endl;
cout << Numb_Digits(test, DECIMALS) << endl;
cout << Numb_Digits(test, WHOLE_NUMBS) << endl;
return 0;
}
It's because of their binary representation, which is discussed in depth here:
http://en.wikipedia.org/wiki/IEEE_754-2008
Basically, when a number can't be represented as is, an approximation is used instead.
To compare floats for equality, check if their difference is lesser than an arbitrary precision.
The easy summary about floating point arithmetic :
http://floating-point-gui.de/
Read this and you'll see the light.
If you're more on the math side, Goldberg paper is always nice :
http://cr.yp.to/2005-590/goldberg.pdf
Long story short : real numbers are stored with a fixed, irregular precision, leading to non obvious behaviors. This is unrelated to the language but more a design choice of how to handle real numbers as a whole.
This is because C++ (like most other languages) can not store floating point numbers with infinte precision.
Floating points are stored like this:
sign * coefficient * 10^exponent if you're using base 10.
The problem is that both the coefficient and exponent are stored as finite integers.
This is a common problem with storing floating point in computer programs, you usually get a tiny rounding error.
The most common way of dealing with this is:
Store the number as a fraction (x/y)
Use a delta that allows small deviations (if abs(x-y) < delta)
Use a third party library such as GMP that can store floating point with perfect precision.
Regarding your question about counting decimals.
There is no way of dealing with this if you get a double as input. You cannot be sure that the user actually sent 1.819999999645634565360 and not 1.82.
Either you have to change your input or change the way your function works.
More info on floating point can be found here: http://en.wikipedia.org/wiki/Floating_point
This is because of the way the IEEE floating point standard is implemented, which will vary depending on operations. It is an approximation of precision. Never use logic of if(float == float), ever!
Float numbers are represented in the form Significant digits × baseexponent(IEEE 754). In your case, float 1.82 = 1 + 0.5 + 0.25 + 0.0625 + ...
Since only a limited digits could be stored, therefore there will be a round error if the float number cannot be represented as a terminating expansion in the relevant base (base 2 in the case).
You should always check relative differences with floating point numbers, not absolute values.
You need to read this, too.
Computers don't store floating point numbers exactly. To accomplish what you are doing, you could store the original input as a string, and count the number of characters.