Reputation: 3473
I am newbie in C# and I can't understand, why my variable doesn't want to increment to value, bigger than 16777215.
I have code:
float fullPerc = 100;
float bytesRead = 1;
long fileSize = 1;
ProgressBar pb1;
int blockSizeBytes = 0;
float counter = 0;
using (FileStream inFs = new FileStream(inFile, FileMode.Open))
{
fileSize = inFs.Length;
do
{
counter = counter + 1;
if (counter > 16777215) //&& counter < 16777230)
{
counter = counter + 10;
//Console.WriteLine(((counter + 10) /100));
}
count = inFs.Read(data, 0, blockSizeBytes);
offset += count;
outStreamEncrypted.Write(data, 0, count);
bytesRead += blockSizeBytes;
}
while (count > 0);
inFs.Close();
}
When value of the counter is equal 16777216, code of the variable increment counter = counter + 1;
doesn't work, but this code
if (counter > 16777215) //&& counter < 16777230)
{
counter = counter + 10;
//Console.WriteLine(((counter + 10) /100));
}
is works fine.
Ie, if I comment this if
code, my counter
will grow up to 16777216 value and will stop on this value. Only increment by 10 will grow this variable, when this variable >=16777216 .
Why?
Upvotes: 1
Views: 624
Reputation: 186668
You have mantissa overflow and as the result a presision loss. float
(or Single
) type has 24 bits mantissa (up to 16777216
):
https://en.wikipedia.org/wiki/Single-precision_floating-point_format
Let's see what's going on:
private static String MakeReport(float value) {
return String.Join(" ", BitConverter
.GetBytes(value)
.Select(b => Convert.ToString(b, 2).PadLeft(8, '0')));
}
...
float f = 16777215;
// Mantissa (first 3 bytes) is full of 1's except the last one bit
// 11111111 11111111 01111111 01001011
Console.Write(MakeReport(f));
// Overflow! Presision loss
// 00000000 00000000 10000000 01001011
Console.Write(MakeReport(f + 1));
// Overflow! Presision loss
// 00000000 00000000 10000000 01001011
Console.Write(MakeReport(f + 2));
// Overflow! Presision loss
// 00000100 00000000 10000000 01001011
Console.Write(MakeReport(f + 10));
Remedy: do not use floating points as counter
but integer:
int counter = 0;
To avoid integer division cast value into double
float x = (float) ((((double)counter * blockSizeBytes) / fileSize) * fullPerc);
Upvotes: 6