Cannot find second part of if-else loop - c++

Hi guys really need your help. There is some problem with my code and i can't figure out whats the error.T
his is my code:
#include<stdio.h>
void main(void)
{
float timeLeavingTP;
int transitNumber;
float transitTime;
printf("Please enter the time leaving TP.\n");
scanf_s("%f",&timeLeavingTP);
printf("Please enter bus number.\n");
scanf_s("%d",&transitNumber);
if(timeLeavingTP==1.00)
{
if(transitNumber==27)
{
printf("The time reached home is 1.54pm.\n");
}
if(transitNumber==8)
{
printf("The time reached home is 1.39pm.\n");
}
if(transitNumber==15)
{
printf("The time reached home is 1.42pm.\n");
}
}
else if(timeLeavingTP==6.30)
{
if(transitNumber==27)
{
printf("The time reached home is 7.32pm");
}
if(transitNumber==8)
{
printf("The time reached home is 7.29pm");
}
if(transitNumber==15)
{
printf("The time reached home is 7.28pm.\n");
}
}
}
After debugging i got
Please enter time leaving TP
1.00
Please enter bus number
27
The time reached home is 1.54pm
Another debugging
Please enter time leaving TP
6.30
Please enter bus number
27
Please enter any key to continue...
May i ask why did the 1.00 work and why the 6.30 do not work. Need your guys help. Thanks a lot!!

This might help you:
http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
You are comparing floating point number for equality which may not work. Also read, the following question:
What is the most effective way for float and double comparison?
This link will also the useful:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Solution which I suggest in your case is to keep time in integer format (by using 24 hour time format such as 1300 etc) which is in integer and there equality comparison will work.
Also read in C++ FAQs: http://www.parashift.com/c++-faq/floating-point-arith.html

You should avoid using floats for time values like these. A float will only equate a literal, if they are EXACTLY the same. Due to way that a computer stores floating point numbers, they are never exactly what you entered (in this case, it could be stored as 6.30000, which won't be equal to 6.30 to the code).
Since you're not doing anything fancy with the time, I'd suggest reading it in as a string, rather than a float.

try using double instead of float for variables.
double timeLeavingTP;
The values of x and y aren't exactly 0.3 and 0.7, as those numbers aren't representable in binary floating point. It happens that the closest float to 0.3 is greater than the closest double to 0.3, and the closest float to 0.7 is less than the closest double to 0.7... hence your comparison results.
Assuming the representations are the same as in C# (where I happen to have some tools to help) the values involved are:
0.3 as float = 0.300000011920928955078125
0.3 as double = 0.299999999999999988897769753748434595763683319091796875
0.7 as float = 0.699999988079071044921875
0.7 as double = 0.6999999999999999555910790149937383830547332763671875
So that explains why it's happening... but it doesn't explain how to work around the issue for whatever your code is actually trying to do, of course. If you can give more context to the bigger problem, we may be able to help more.

When comparing float to constant you should use extension f
like this:
else if(timeLeavingTP==6.30f)
You really shouldn't use a float for time value. 6.30 is 6:30 or 6:18? what will happen if we add 1.40 to 6.30?

Ok, already a lot of answers. Some additional information:
In C++ standard, section 2.14.14, it is stated that:
The type of a floating literal is double unless explicitly specified by a suffix.
This means that you compare your float variable with a double constant. Unfortunately floating point conversion (float and double) can give very small differences. But the difference is smaller for double which are more precise than for float. This is why your float doesn't match the double.
To avoid this, either use two doubles (see a lot of other responses above), or use two floats, by changing your else if to:
else if (timeLeavingTP == 6.30f)

6.30 looks like a nice simple floating-point number, and in decimal it is, but in binary floating point it is not. 6.30 cannot be represented by a float, and it cannot be represented by a double. It cannot be perfectly represented by any binary floating-point number.
When you write this statement (after assigning 6.30 to timeLeavingTP):
if(timeLeavingTP==6.30)
what you are actually doing is this:
if((float)6.30==(double)6.30)
You are comparing the 32-bit float representation of 6.30 to the 64-bit double representation of 6.30. Both are approximations. The double representation is a closer approximation. Therefore they are not equal.
You could add an epsilon to allow for this slop, but better solutions would be to use 6.30f as your constant (make the right side also a float) or make timeLeavingTP a double. The goal is not to get greater accuracy, but to have consistent accuracy.
See this article for details on this exact problem:
http://randomascii.wordpress.com/2012/06/26/doubles-are-not-floats-so-dont-compare-them/

try this:
#include<stdio.h>
void main(void)
{
float timeLeavingTP;
int transitNumber;
float transitTime;
printf("Please enter the time leaving TP.\n");
scanf_s("%f",&timeLeavingTP);
printf("Please enter bus number.\n");
scanf_s("%d",&transitNumber);
if(timeLeavingTP==1.00)
{
if(transitNumber==27)
{
printf("The time reached home is 1.54pm.\n");
}
if(transitNumber==8)
{
printf("The time reached home is 1.39pm.\n");
}
if(transitNumber==15)
{
printf("The time reached home is 1.42pm.\n");
}
}
if(timeLeavingTP==6.30)
{
if(transitNumber==27)
{
printf("The time reached home is 7.32pm");
}
if(transitNumber==8)
{
printf("The time reached home is 7.29pm");
}
if(transitNumber==15)
{
printf("The time reached home is 7.28pm.\n");
}
}
}

Related

problem in using 'double' data type in for loops with fractional incrementation [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
I had a program which requires one to search values from -100.00 to +100.00 with incrementation of 0.01 inside a for loop. But the if conditions arent working properly even if code is correct...
As an example I tried printing a small section i.e if(i==1.5){cout<<"yes...";}
it was not working even though the code was attaining the value i=1.5, i verified that by printing each of the values too.
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
double i;
for(i=-1.00; i<1.00; i=i+0.01)
{
if(i>-0.04 && i<0.04)
{
cout<<i;
if(i==0.01)
cout<<"->yes ";
else
cout<<"->no ";
}
}
return 0;
}
Output:
-0.04->no -0.03->no -0.02->no -0.02->no -0.01->no 7.5287e-016->no 0.01->no 0.02->no 0.03->no
Process returned 0 (0x0) execution time : 1.391
(notice that 0.01 is being attained but still it prints 'no')
(also notice that 0.04 is being printed even if it wasn't instructed to do so)
use this if(abs(i - 0.01) < 0.00000000001) instead.
double - double precision floating point type. Usually IEEE-754 64 bit
floating point type
The crux of the problem is that numbers are represented in this format as a whole number times a power of two; rational numbers (such as 0.01, which is 1/100) whose denominator is not a power of two cannot be exactly represented.
In simple word, if the number can't be represented by a sum of 1/(2^n) you don't have the exact number you want to use. So to compare two double numbers calculate the absolute difference between them and use a tolerance value e.g. 0.00000000001 .
Doubles are stored in binary format. To cut things short fractional part is written as binary. Now let's imagine it's size is 1 bit. So you've two possible values (for fraction only): .0 and .5. With two bits you have: .0 .25 .5 .75. With three bits: .125 .25 .375 .5 .625 .75 .875. And so on. But you'll never get 0.1. So what computer does? It cheats. It lies to you, that 0.1 you see is 0.1. While it more looks like 0.1000000000000000002 or something like this. Why it looks like 0.1? Because formatting of floating point values has long standing tradition of rounding numbers, so 0.10000000000001 becomes 0.1. As a result 0.1 * 10 won't equal 1.0.
Correct solution is to avoid floating point numbers, unless you don't care for precision. If your program breaks, once your floating point value "changes" by miniscule amount, then you need to find another way. In your case using non-fractional values will be enough:
for(auto ii=-100; ii<100; ++ii)
{
if(ii>-4 && ii<4)
{
cout << (ii / 100.0);
if(ii==1)
cout<<"->yes ";
else
cout<<"->no ";
}
}

C++ decimal checking if statement errors?

I'm doing some homework for a C++ class, and i'm pretty new to C++. I've run into some issues with my if statement... What i'm doing, is i have the user input a time, between 0.00 and 23.59. the : is replaced by a period btw. that part works. i then am seperating the hour and the minute, and checking them to make sure that they are in valid restraints. checking the hour works, but not the minute... heres my code:
minute= startTime - static_cast<int>(startTime);
hour= static_cast<int>(startTime);
//check validity
if (minute > 0.59) {
cout << "ERROR! ENTERED INVALID TIME! SHUTTING DOWN..." << endl;;
return(0);
}
if (hour > 23) {
cout << "ERROR! ENTERED INVALID TIME! SHUTTING DOWN..." << endl;;
return(0);
}
again, the hour works if i enter 23, but if i enter 23.59, i get the error, but if i enter 23.01 i do not. also, if i enter 0.59 it also gives the error, but not 0.58. I tried switching the if(minute > 0.59) to if(minute > 0.6) but for some reason that caused problems elsewhere. i am at a complete loss as to what to do, so any help would be great! thanks a million!
EDIT: i just entered 0.58, and it didnt give me the error... but if i make it a 1.59 it gives an error again... also, upvotes would be nice :D
Floating-point arithmetic (float and double) is inherently fuzzy. There are always some digits behind the decimal point that you don't see in the rounded representation that is sent to your stream, and comparisons can also be fuzzy because the representation you are used to (decimal) is not the one the computer uses (binary).
Represent a time as int hours and int minutes, and your problems will fade away. Most libraries measure time in ticks (usually seconds or microseconds) and do not offer sub-tick resolution. You do well to emulate them.
Comparison of floating point numbers is prone to failure, because very few of them can be represented exactly in base 2. There's always going to be some possibility that two different numbers are going to round in different directions.
The simplest fix is to add a very tiny fudge factor to the number you're comparing:
if (minute > 0.59 + epsilon)
See What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Don't, ever, use double (nor float) to store two integer values using the integer and decimal part as separator. The decimal data types are not precise enough, so you may have wrong results (in case of a round).
A good solution in your case is either to use a struct (or a pair) or even an integer.
With integer, you can use mod or div of multiples of then to extract the real value. Example:
int startTime = 2359;
int hour = startTime / 100;
int minute = startTime % 100;
Although, with struct the code would look simpler and easier to understand (and to maintain).
There's no way you can compare to exactly 0.59; this value
cannot be represented in the machine. You're comparing
something which is very close to 0.59 with something else that
is very close to 0.59.
Personally, I wouldn't input time this way at all. A much
better solution would be to learn how to use std::istream to
read the value. But if you insist, and you have startTime as
your double, you need to multiply it by 100.0 (so that all
of the values that interest you are integers, and can be
represented exactly), then round it, then convert it to an
integer, and use the modulo and division operators on the
integer to extract your values. Something along the lines of:
assert( startTime >= 0.0 && startTime <= 24.0 );
int tmpTime = 100.0 * startTime + 0.5;
int minute = tmpTime % 100;
int hour = tmpTime / 100;
When dealing with integral values, it's much simpler to use
integral types.

visual studio 2010 showing weird behavior on float/double increment [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Dealing with accuracy problems in floating-point numbers
I am writing an OpenGl animation and am using a float variable "time" to keep track of the time.
I am incrementing the "time" variable by 0.01 .I have certain conditions to fulfil whenever "time" reaches an integer value.The issue is that after a certain time the float increment shows weird behavior.
I start from time = 0 and I see that after "time" reaches 0.83 the next value is 0.839999.
I though this could be related to float precision so I tried using double/long double and I found that instead of reaching the value 1.00 the code is reaching the value 1.0000007.
I tried incrementing by "0.01f" instead of "0.01" but got no success.
Is this some bug in Visual Studio or am I doing it the wrong way?
I could post the code but I don't think it's of much use as I am assigning to "time" just at one place and it's just being used at other places.
Don't ever compare floating point values for equality unless you know exactly what you are doing. I would strongly suggest you use integers (perhaps integer numbers of milliseconds) for this purpose.
See What Every Computer Scientist Should Know About Floating-Point Arithmetic for more information.
Floating point is a fixed-precision format. This is an inherent limitation of fixed-precision formats.
For example, say you used six decimal digits of precision. One-third would be .333333. But if you add one-third three times, you get .999999, not 1. That's the nature of the beast.
Not exactly recommending this, but the issue is that the 0.1 cannot be represented exactly as double. 1.0 can be. So if you make your time-step a (negative) power of two, you will find a difference. By way of illustration:
double delta = 1.0 / 8;
int stopper = 10;
int nextInt = 1;
for (double t = 0; t <= stopper; t += delta)
{
if (t == nextInt)
{
std::cout << "int ";
++nextInt;
}
else
std::cout << " ";
std::cout << t << std::endl;
}
Just round "time" after each increment to make sure it maintains a sensible value.
Something like that:
double round(double value, double precision)
{
return floor(value / precision + 0.5) * precision;
}
time = round(time + 0.1, 0.1);

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.

C/C++ rounding up decimals with a certain precision, efficiently

I'm trying to optimize the following. The code bellow does this :
If a = 0.775 and I need precision 2 dp then a => 0.78
Basically, if the last digit is 5, it rounds upwards the next digit, otherwise it doesn't.
My problem was that 0.45 doesnt round to 0.5 with 1 decimalpoint, as the value is saved as 0.44999999343.... and setprecision rounds it to 0.4.
Thats why setprecision is forced to be higher setprecision(p+10) and then if it really ends in a 5, add the small amount in order to round up correctly.
Once done, it compares a with string b and returns the result. The problem is, this function is called a few billion times, making the program craw. Any better ideas on how to rewrite / optimize this and what functions in the code are so heavy on the machine?
bool match(double a,string b,int p) { //p = precision no greater than 7dp
double t[] = {0.2, 0.02, 0.002, 0.0002, 0.00002, 0.000002, 0.0000002, 0.00000002};
stringstream buff;
string temp;
buff << setprecision(p+10) << setiosflags(ios_base::fixed) << a; // 10 decimal precision
buff >> temp;
if(temp[temp.size()-10] == '5') a += t[p]; // help to round upwards
ostringstream test;
test << setprecision(p) << setiosflags(ios_base::fixed) << a;
temp = test.str();
if(b.compare(temp) == 0) return true;
return false;
}
I wrote an integer square root subroutine with nothing more than a couple dozen lines of ASM, with no API calls whatsoever - and it still could only do about 50 million SqRoots/second (this was about five years ago ...).
The point I'm making is that if you're going for billions of calls, even today's technology is going to choke.
But if you really want to make an effort to speed it up, remove as many API usages as humanly possible. This may require you to perform API tasks manually, instead of letting the libraries do it for you. Specifically, remove any type of stream operation. Those are slower than dirt in this context. You may really have to improvise there.
The only thing left to do after that is to replace as many lines of C++ as you can with custom ASM - but you'll have to be a perfectionist about it. Make sure you are taking full advantage of every CPU cycle and register - as well as every byte of CPU cache and stack space.
You may consider using integer values instead of floating-points, as these are far more ASM-friendly and much more efficient. You'd have to multiply the number by 10^7 (or 10^p, depending on how you decide to form your logic) to move the decimal all the way over to the right. Then you could safely convert the floating-point into a basic integer.
You'll have to rely on the computer hardware to do the rest.
<--Microsoft Specific-->
I'll also add that C++ identifiers (including static ones, as Donnie DeBoer mentioned) are directly accessible from ASM blocks nested into your C++ code. This makes inline ASM a breeze.
<--End Microsoft Specific-->
Depending on what you want the numbers for, you might want to use fixed point numbers instead of floating point. A quick search turns up this.
I think you can just add 0.005 for precision to hundredths, 0.0005 for thousands, etc. snprintf the result with something like "%1.2f" (hundredths, 1.3f thousandths, etc.) and compare the strings. You should be able to table-ize or parameterize this logic.
You could save some major cycles in your posted code by just making that double t[] static, so that it's not allocating it over and over.
Try this instead:
#include <cmath>
double setprecision(double x, int prec) {
return
ceil( x * pow(10,(double)prec) - .4999999999999)
/ pow(10,(double)prec);
}
It's probably faster. Maybe try inlining it as well, but that might hurt if it doesn't help.
Example of how it works:
2.345* 100 (10 to the 2nd power) = 234.5
234.5 - .4999999999999 = 234.0000000000001
ceil( 234.0000000000001 ) = 235
235 / 100 (10 to the 2nd power) = 2.35
The .4999999999999 was chosen because of the precision for a c++ double on a 32 bit system. If you're on a 64 bit platform you'll probably need more nines. If you increase the nines further on a 32 bit system it overflows and rounds down instead of up, i. e. 234.00000000000001 gets truncated to 234 in a double in (my) 32 bit environment.
Using floating point (an inexact representation) means you've lost some information about the true number. You can't simply "fix" the value stored in the double by adding a fudge value. That might fix certain cases (like .45), but it will break other cases. You'll end up rounding up numbers that should have been rounded down.
Here's a related article:
http://www.theregister.co.uk/2006/08/12/floating_point_approximation/
I'm taking at guess at what you really mean to do. I suspect you're trying to see if a string contains a decimal representation of a double to some precision. Perhaps it's an arithmetic quiz program and you're trying to see if the user's response is "close enough" to the real answer. If that's the case, then it may be simpler to convert the string to a double and see if the absolute value of the difference between the two doubles is within some tolerance.
double string_to_double(const std::string &s)
{
std::stringstream buffer(s);
double d = 0.0;
buffer >> d;
return d;
}
bool match(const std::string &guess, double answer, int precision)
{
const static double thresh[] = { 0.5, 0.05, 0.005, 0.0005, /* etc. */ };
const double g = string_to_double(guess);
const double delta = g - answer;
return -thresh[precision] < delta && delta <= thresh[precision];
}
Another possibility is to round the answer first (while it's still numeric) BEFORE converting it to a string.
bool match2(const std::string &guess, double answer, int precision)
{
const static double thresh[] = {0.5, 0.05, 0.005, 0.0005, /* etc. */ };
const double rounded = answer + thresh[precision];
std::stringstream buffer;
buffer << std::setprecision(precision) << rounded;
return guess == buffer.str();
}
Both of these solutions should be faster than your sample code, but I'm not sure if they do what you really want.
As far as i see you are checking if a rounded on p points is equal b.
Insted of changing a to string, make other way and change string to double
- (just multiplications and addion or only additoins using small table)
- then substract both numbers and check if substraction is in proper range (if p==1 => abs(p-a) < 0.05)
Old time developers trick from the dark ages of Pounds, Shilling and pence in the old country.
The trick was to store the value as a whole number fo half-pennys. (Or whatever your smallest unit is). Then all your subsequent arithmatic is straightforward integer arithimatic and rounding etc will take care of itself.
So in your case you store your data in units of 200ths of whatever you are counting,
do simple integer calculations on these values and divide by 200 into a float varaible whenever you want to display the result.
I beleive Boost does a "BigDecimal" library these days, but, your requirement for run time speed would probably exclude this otherwise excellent solution.