If you enter 0.24 as the input, the float will store (if it's a 32 bit float) 0.23999999463558197021484375
Multiply that by 100. You get 23.999999463558197021484375, except that the float can't hold that value. It will hold a value close to it.
What's the closest floating point representation to that? 24
The number 24 CAN be exactly represented.
Nwb, you can start playing around with floating point numbers yourself ( https://www.h-schmidt.net/FloatConverter/IEEE754.html ) and work out what you particular system is doing. Just remember, there are no guarantees on the accuracy of floating point computation in C++.
@Peter round works only for integers, so I am potentially losing an important decimal point if I use the function for round(). (How do I know when to round? and what if the user inputted 2.99!?)
Are we still trying to solve the same problem as at the beginning of this pagethe previous page (page 2)? If so, I don't think floating point numbers should be used at all.
how is it that when you ran my program you got 23 but when you tried that bit of code you got 24?
I don't know. Did you read the link that Repeater posted about "Floating-Point Determinism"? I don't think it is very useful to try and understand exactly what happens with floating point values. Just accept that they are approximations with rounding errors and write your code accordingly. If you need exact calculations use integers (or types built on top of integers).
We're riffing on the theme of how might one particular case be working to produce the output we're seeing, but just for the fun of it.
Changing anything at all could produce different outputs. Floating point sacrifices accuracy.
If you NEED the accuracy, if you NEED the user to be able to enter 0.24 and for the value 0.24 to be exactly represented with a datatype, then you NEED to use a datatype that can do that - NOT floating point.
@nwd, trying to understand what's going on inside the processor and the running executable is fun and educational, but the lesson here is NOT that there is some way to make floating point perfectly accurate and reliable. There isn't. That's not what it's for.
But @Peter why did you get two different answers when you did the same computation! Are you saying that it's random in that it could be both 23 or 24?
How float is calculated is by binary, but how it is rounded off is dependont on the compiler? Is that how this works? Or all compilers use the same standard? I still donno how float round works but I guess it doesn't matter at this point..
At this point I'm just curious I'm not trying to use floating point arithmetic to find out how many decimals an inputted number has.. anymore.. lol ;)
// Example program
#include <iostream>
#include <cmath>
#include <limits>
#include <iomanip>
int main()
{
longdouble original = 0.24;
longdouble n = original * 10 * 10; // produces more rounding error
std::cout << std::setprecision(100);
std::cout << n << '\n';
longdouble next = std::nextafter(n, std::numeric_limits<decltype(n)>::max());
while (next <= 24.0)
{
std::cout << next << '\n';
next = std::nextafter(next, std::numeric_limits<decltype(n)>::max());
}
}
Peter you said that if you write 0.24L you would get 24. So just curious, how do I force the compiler to take input as long double and not double and then convert to long double?
@ganado that's cool. Maybe I could use that! Thanks a lot!
I was thinking.. How about we use the previous logic.. And if the value still have floating point after the while loop, we directly multiply the input number by 10^8 (to avoid flooding rounding errors) call nextafter() once, check for floating point and put that in loop to count how many nexafters it took to lose the floating point.
Using this data could estimate how many nextafters it takes for a legit input to get to its integer representation. Remember that all integers can be represented in binary.
> we directly multiply the input number by 10^8 (to avoid flooding rounding errors) call nextafter() once,
> check for floating point and put that in loop to count how many nexafters it took to lose the floating point.
The ULP may already be greater than one when we multiply the input number by 10^8.
Assuming that std::numeric_limits<double>::is_iec559 is true (IEEE 754: true for all current floating-point hardware), the IEEE 754 guarantee is only that a floating point computation is accurate to within half ULP.
Elaborate please? I don't get what ULP is. Or is_iec559
Are you saying that it loses precision by then? What if we multiply only until the number is 8digits (that's what I meant initially but I see that I phrased it wronlgy).
If it still had floating point or if number itself is greater than 8 digits, we prompt that the number is not supported.
Is 8 digits the maximum number I can take without losing precision for long double?
I want to support as many digits as I can as long as I'm accurate.. Also position of the point doesn't affect the precision does it? Only number of digits right?
Temp_floating - truncate(temp_floating) should return 0 if the Value of temp is 24 or - 1 if its 23 with decimal places. You got - 1..
Yes, but this had nothing to do with conversion from double to long double. If I changed the type to double it worked correctly. It was when long double was used that it gave me trouble, but only when the number was multiplied with 10 twice instead of 100 once. http://www.cplusplus.com/forum/beginner/244856/3/#msg1084156
Yes. In simple terms, the value of the ULP (Unit of Least Precision) is the distance between a representable floating point number and the next higher representable floating point number.
If the ULP is 8 for a floating point number x, the next representable floating point number is x+8
ie. x+1, x+2 etc. can't be represented.
Here is an example, where the ULP is 8:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <iostream>
#include <iomanip>
#include <boost/math/special_functions/ulp.hpp>
int main()
{
float f = 100'000'000 ;
std::cout << std::fixed << std::setprecision(0) ;
std::cout << "value: " << f << " ulp: " << boost::math::ulp(f) << '\n' ;
for( int i = 0 ; i < 32 ; ++i )
std::cout << f << " + " << std::setw(2) << i << " yields " << f+i << '\n' ;
}
Are you saying that even some whole integers cannot be represented in floating? I don't get it..
We want to use nextafter() to find a floating point that will eventually be a value without a floating point like 2.0 So whatever numbers come before 2.0 don't matter.. I don't think I understand you properly.
@Peter when you ran my demonstration program you got 23 right.. Was that because of continuous 10 multiplication in while loop?
I think you need to stop guessing and asking disconnected questions and actually take the time to learn how floating point works. Then you'll be able to answer all your questions yourself.
Was that because of continuous 10 multiplication in while loop?
I don't know if you can say that. Sure, if you had done it some other way (e.g. multiplied with 100 in each step) it might have worked for this particular case but that would just be a coincidence. Don't forget that 0.24 when stored as a floating point number is not exactly 0.24 so when multiplied with some number k the "correct" answer is in fact not equal to 0.24 * k. If 0.24 * k can be represented exactly you might get lucky and get exactly this value due to rounding errors but I wouldn't count on it.