I am learning c by watching udemy online course by vlad budnitski.
I know I used the wrong format specifier in my C program when reading floats into int variables using scanf(“%f”, &variable).
Can someone explain why I get such a large, random value for the area calculation?
How do the input values get converted to these random values?
#include <stdio.h>
#include <stdlib.h>
// Width Height --> Floating Point
float findArea (float width, float height)
{
float area;
area = width* height;
printf("width:%fn",width);
printf("height:%fn",height);
return area;
}
int main(){
int heightRectangle, widthRectangle;
float area;
printf("Enter width: ");
scanf("%f",&widthRectangle);
printf("Enter height: ");
scanf("%f", &heightRectangle);
area = findArea(widthRectangle,heightRectangle);
printf("The area of your given rectangle is: %f n",area);
return 0;
}
Output:
Enter width: 5.0
Enter height: 2.5
width:1084227584.000000
height:1075838976.000000
The area of your given rectangle is: 1166454293721513984.000000
Size of int and float in my system is 4bytes .I used sizeof operator to determine that.
Compiler Information:
I am using online compiler programiz
Guys, once again i know I used wrong format specifier.I’m just expecting answer which explains how the values 5.0 and 2.5 are getting converted to 1084227584 and 1075838976.
J KR is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
The %f
in scanf("%f",&widthRectangle);
instructs scanf
to convert input into the encoding scheme used for a float
object and to store the bits that result from that encoding in the memory pointed to by widthRectangle
.
Since, in main
, widthRectangle
is declared to be an int
, when widthRectangle
is used in findArea(widthRectangle,heightRectangle)
, the program interprets those bits using the encoding scheme used for an int
. Then, because findArea
is declared to have float
parameters, the program converts that value to the float
type and passes that to findArea
.
So the value later printed by printf("width:%fn",width)
is the result of interpreting the encoding of 5
as a float
using the decoding for int
.
Everything we represent in a computer is encoded by some arbitrary assignment of what bits represent what value. int
and float
types use different rules for what bits represent what values.
For int
types, two’s complement is usually used. First, we start with rules
for encoding a non-negative integer in binary:
To encode a non-negative integer x in w bits (w for “width”):
- Let bi denote the bit that is i bits from the right, starting with b0 for the rightmost bit.
- For i from 0 to w−1:
- If x is even or odd, set bi to 0 or 1, respectively.
- Set x to x / 2, truncating any fraction.
- If x is not zero after the above, it does not fit in w bits. Declare an error and stop.
To encode an integer x in w-bit two’s complement:
- If x exceeds 2w−1−1 or is less than −2w−1, it does not fit. Declare an error and stop.
- If x is negative, set x to x + 2w.
- Encode x in w-bit binary, per above.
For float
types, a multi-part encoding of the number with separate sign, exponent, and significand portions is used. Most commonly, the IEEE-754 binary32 format is used. To keep this simple, we will assume a real number x exactly fits within the format—it is within the exponent range and does not need any rounding. In real code, it is necessary to handle overflow and rounding.
- If x is negative or not, let S be the bit 1 or 0, respectively, and set x to |x|.
- Set an exponent e to 0.
- While 2 ≤ x:
- Set e to e+1.
- Set x to x/2 (retaining any fraction).
- While x < 1 and −126 < e:
- Set e to e−1.
- Set x to 2x.
- Set f to 223•x, rounded to an integer. (There is a choice of rounding methods, not discussed here.)
- If 224 ≤ f, set e to e+1 and set f to f/2. (f will now be exactly 223.)
- If 127 < e, x was too large. Declare overflow and stop.
- If f < 223:
- Let E be a string of eight 0 bits.
- Let F be the result of encoding f in 23 bits in binary.
- Otherwise:
- Let E be the result of encoding e+127 in eight bits in binary.
- Let F be the result of encoding f−223 in 23 bits in binary.
- The resulting bit string is the concatenation of S, E, and F.
For 5, this operates:
- In step 1, 5 is not negative, so S is set to 0.
- In step 2, e is set to 0.
- In step 3:
- 5 is greater than 2, so e is increased to 1 and x is changed to 2.5.
- 2.5 is greater than 2, so e is increaed to 2, and x is changed to 1.25.
- 1.25 is not greater than 2, so the loop in step 3 stops.
- In step 4, 1.25 is not less than 1, so the loop in step 4 does not start.
- In step 5, f is set to 223•1.25 = 10,485,760 = A0000016.
- In step 6, f is not greater than or equal to 224, so nothing is done.
- In step 7, e is not greater than 127, so nothing is done.
- In step 8, f is not less than 223, so nothing is done.
- In step 9, E is set to the eight bits resulting from encoding 127+2 in binary, which is the string 10000001, and F is set to the result of encoding 10,485,760 − 223 in 23 bits in binary, which is 01000000000000000000000.
- In step 10, the result is the concatenation of 0, 10000001, and 01000000000000000000000, making
01000000101000000000000000000000.
When the bit string 01000000101000000000000000000000 is interpreted as an int
, the result is 1,084,227,584.
We can also reverse this:
In hexadecimal, 1,084,227,584 is 40A00000. In 32-bit binary, this is 0 10000001 01000000000000000000000. I inserted spaces to show where we separate the number into parts due to the floating-point encoding scheme. The first bit, 0, means positive. The next eight bits, 10000001, are an encoding of the exponent (and one bit of the significand, a leading 1). As a binary numeral, they would be the number 129. The floating-exponent exponent is this number minus 127, so it is 2. The last 23 bits are the last 23 bits of the significand. Together with the leading 1 bit, they represent binary 1.01000000000000000000000, which is 1.25 in decimal. Thus, the floating-point number represented is + 22 • 1.25, which is 5.
Similarly, 1,075,838,976 is hexadecimal 40200000, binary 0 10000000 01000000000000000000000, which differs only in that the exponent field is binary 10000000, decimal 128, so it represents the exponent 1. The floating-point number represented is + 21 • 1.25, which is 2.5.