Improper Double Calculations [duplicate] - c++

Teaching myself C and finding that when I do an equation for a temp conversion it won't work unless I change the fraction to a decimal. ie,
tempC=(.555*(tempF-32)) will work but tempC=((5/9)*(tempF-32)) won't work.
Why?
According to the book "C Primer Plus" it should work as I'm using floats for both tempC and tempF.

It looks like you have integer division in the second case:
tempC=((5/9)*(tempF-32))
The 5 / 9 will get truncated to zero.
To fix that, you need to make one of them a floating-point type:
tempC=((5./9.)*(tempF-32))

When you do 5/9, 5 and 9 are both integers and integer division happens. The result of integer division is an integer and it is the quotient of the two operands. So, the quotient in case of 5/9 is 0 and since you multiply by 0, tempC comes out to be 0. In order to not have integer division, atleast one of the two operands must be float.
E.g. if you use 5.0/9 or 5/9.0 or 5.0/9.0, it will work as expected.

5/9 is an integer division not a floating point division. That's why you are getting wrong result.
Make 5 or 9 floating point variable and you will get correct answer.
Like 5.0/9 OR 5/9.0

5/9 is an integer expression, as such it gets truncated to 0. your compiler should warn you about this, else you should look into enabling warnings.

If you put 5/9 in parenthesis, this will be calculated first, and since those are two integers, it will be done by integer division and the result will be 0, before the rest of the expression is evaluated.
You can rearrange your expression so that the conversion to float occurs first:
tempC=((5/9)*(tempF-32)); → tempC=(5*(tempF-32))/9;
or of course, as the others say, use floating point constants.

Related

C++ std::remainder() function returning (incorrect) negative values for a pair of positive numbers [duplicate]

This question already has answers here:
understanding std::fmod and std::remainder
(2 answers)
Closed last month.
I'm trying to obtain the remainder of two float numbers in C++ for some calculations and I found out that the built in std::remainder() function doesn't always return what I expect to.
For a concrete example, std::remainder(683.242, 27.8576183) returns -13.1985, instead of ~14.66. I realized that -13.1985 is what you would have to add to 27... to obtain the correct remainder, which makes me suspect that -13... is the expected result and I'm missing something about what std::remainder() really does.
I'd be thankful if someone could tell me why std::remainder() returns negative values, or point me to some function / library that I can actually use to obtain 'normal' remainders from decimal numbers.
Ok, this was short, but I found out that I'm, indeed, not supposed to use std::remainder() to get the remainder. The function that actually returns the mathematical 'normal' remainder is std::fmod() because reasons.
The reason std::remainder() doesn't work is because it rounds the quotient towards the nearest integer, as explained here. This also explains why the negative remainders I were getting were the difference between the divisor and the expected remainder.
The floating-point remainder of the division operation x/y calculated by std::remainder(x,y) is exactly the value x - n*y, where the value n is the integral value nearest the exact value x/y. If |n-x/y| = 0.5 (precisely), the value n is then chosen to be even.
So the returned value is not guaranteed to have the same sign as x.
If it rounds one way you get a positive number, if you round another you can get a negative one. Consider using std::fmod(...)

the program written in fortran 95 and it showing warning integer division truncated to '0' [-Winteger-division] and some output data is NaN [duplicate]

I'm writing out the elements of an array as follows:
write(6,'(i4,200(1x,e15.7))')Jtot0, (a*PJjv(i,Jtot0,j,iv),i=1,nenerdif,100)
where a is a constant. However, when this constant is equal to 1/2 or 1/3 the output is zeros, and if it's equal to 1, every thing goes well. The array elements are real*8.
How can I overcome this, giving that I'm obligated to multiply by a factor of 1/3?
In Fortran 1/2 is an integer division operation which will round down to, in this case, 0. Same for 1/3. If you want a real result, do a real division operation, such as 1.0/2.0. Note that assigning the result of 1/2 to a real variable will set the real variable to 0.0, that is the integer division will result in 0 and the assignment, which happens next, will cast that value to its nearest real representation.
This business of integer division producing integer results is very common in programming languages.

Why does changing the product operand order change the result of the expression when constants are involved? [duplicate]

Teaching myself C and finding that when I do an equation for a temp conversion it won't work unless I change the fraction to a decimal. ie,
tempC=(.555*(tempF-32)) will work but tempC=((5/9)*(tempF-32)) won't work.
Why?
According to the book "C Primer Plus" it should work as I'm using floats for both tempC and tempF.
It looks like you have integer division in the second case:
tempC=((5/9)*(tempF-32))
The 5 / 9 will get truncated to zero.
To fix that, you need to make one of them a floating-point type:
tempC=((5./9.)*(tempF-32))
When you do 5/9, 5 and 9 are both integers and integer division happens. The result of integer division is an integer and it is the quotient of the two operands. So, the quotient in case of 5/9 is 0 and since you multiply by 0, tempC comes out to be 0. In order to not have integer division, atleast one of the two operands must be float.
E.g. if you use 5.0/9 or 5/9.0 or 5.0/9.0, it will work as expected.
5/9 is an integer division not a floating point division. That's why you are getting wrong result.
Make 5 or 9 floating point variable and you will get correct answer.
Like 5.0/9 OR 5/9.0
5/9 is an integer expression, as such it gets truncated to 0. your compiler should warn you about this, else you should look into enabling warnings.
If you put 5/9 in parenthesis, this will be calculated first, and since those are two integers, it will be done by integer division and the result will be 0, before the rest of the expression is evaluated.
You can rearrange your expression so that the conversion to float occurs first:
tempC=((5/9)*(tempF-32)); → tempC=(5*(tempF-32))/9;
or of course, as the others say, use floating point constants.

Why is (long) always rounding the number down?

Yesterday I faced a problem that I could not explain. I was writing a very simple function that converts a double number to long. It was a part of another program. I used the following code:
long converter(double x) {
return (long) x;
}
It worked perfectly until I entered 1.9 as the input and the result was 1. But 1.9 is closer to 2 than it is to 1. So, the result should be 2 rather than 1.
Why is this problem happening? Can you give me a solution that solves this irritating problem?
Casting it to long won't round it as you expect. It will just discard the fractional part and will give you integer part . Therefore , you get 1 not 2.
You can refer std::lround here .
Casting to long does not round a number correctly. To do that, you have to use std::lround(). Just use the following code:
long converter(double x) {
return std::lround(x);
}
This should get the job done. Also, remember to include <cmath> in your code. Otherwise, it might not work.
P.S. std::lround() may not be compatible with older compilers. So, remember to use the latest version of your compiler.
You can use like
long converter(double x){
if(x>0)
return (long)(x+0.5);
else
return (long)(x-0.5);
}
As casting discard fractional part you can not get what you expect. Adding '0.5' take the number to next long if fraction greater than '0.5'.
Type casting from an floating point type to integral type will (if it will fit) do so by just discarding the fractional part. That is 1.9 converts to 1 and -1.9 converts to -1.
The reason this was done is due to the way floating point values are stored (if there were an ambiguity here they would probably have chosen this conversion to be implementation defined to some degree). The number is contains of three parts: the sign, the mantissa and the exponent. These are binary, but the decimal equivalent would be +1.9e+0 where + is the sign, 1.9 is the mantissa and +0 is the exponent. The conversion of the mantissa+exponent to an integer becomes quite easy and fast if you just take the mantissa and shifts it to be an integer. After that you apply the sign. So the operation becomes to mask out the mantissa, and exponent and then doing a shift and last negate if the sign bit is set.
Had they chosen to actually do a proper rounding one would just have to do a little more job. The standard settled for the somewhat easier solution for defining the cast.

Incorrect floating point math?

Here is a problem that has had me completely baffled for the past few hours...
I have an equation hard coded in my program:
double s2;
s2 = -(0*13)/84+6/42-0/84+24/12+(6*13)/42;
Every time i run the program, the computer spits out 3 as the answer, however doing the math by hand, i get 4. Even further, after inputting the equation into Matlab, I also get the answer 4. Whats going on here?
The only thing i can think of that is going wrong here would be round off error. However with a maximum of 5 rounding errors, coupled with using double precision math, my maximum error would be very very small so i doubt that is the problem.
Anyone able to offer any solutions?
Thanks in advance,
-Faken
You're not actually doing floating point math there, you're doing integer math, which will floor the results of divisions.
In C++, 5/4 = 1, not 1.25 - because 5 and 4 are both integers, so the result will be an integer, and thus the fractional part of the result is thrown away.
On the other hand, 5.0/4.0 will equal approx. 1.25 because at least one of 5.0 and 4.0 is a floating-point number so the result will also be floating point.
You're confusing integer division with floating point division. 3 is the correct answer with integer division. You'll get 4 if you convert those values to floating point numbers.
Some of this is being evaluated using integer arithmetic. Try adding a decimal place to your numbers, e.g. 6.0 instead 6 to tell the compiler that you don't want integer arithmetic.
s2 = -(0*13)/84+6/42-0/84+24/12+(6*13)/42;
yields 3
s2 = -(0.*13.)/84.+6./42.-0./84.+24./12.+(6.*13.)/42.;
does what you are expecting.