Arithmetic Division

J

Joe Cool

Hello, I am using VS2005. I am trying to convert a VB.NET app to
C#.NET. The VB app uses a progress meter to indiate how far a file has
been read. I use the following assignment statement in VB:

Progress.Value = (lFileReadCount / fi.Length) * 100

lFileReadCount is a Long that contains the current number of bytes
read. fi is a FileInfo object of the file being read. Progress is
shown as a percentage.

In C# the statement is:

Progress.Value = (lFileReadCount / fi.Length) * 100;

Obviously the only difference is the semi-colon at the end. Problem
is, the value of the progress meter never changes from zero.

I put in debug statements and lFileReadCount and fi.Length are what
you would expect. I also put in a debug statement to display the
result of the arithmentic operation, and the result is ALWAYS ZERO!!!

What gives?!?!?
 
M

Morten Wennevik [C# MVP]

Hi Joe,

Did you specify the range of the Progress bar?
Check Maximum and Minimum and verify that Value isn't outside that range..
 
A

Alberto Poblacion

Joe Cool said:
Hello, I am using VS2005. I am trying to convert a VB.NET app to
C#.NET. The VB app uses a progress meter to indiate how far a file has
been read. I use the following assignment statement in VB:

Progress.Value = (lFileReadCount / fi.Length) * 100

lFileReadCount is a Long that contains the current number of bytes
read. fi is a FileInfo object of the file being read. Progress is
shown as a percentage.

In C# the statement is:

Progress.Value = (lFileReadCount / fi.Length) * 100;

Obviously the only difference is the semi-colon at the end. Problem
is, the value of the progress meter never changes from zero.

I put in debug statements and lFileReadCount and fi.Length are what
you would expect. I also put in a debug statement to display the
result of the arithmentic operation, and the result is ALWAYS ZERO!!!


The "/" in C#, when aplied to two integer values, is not equivalent to
the "/" in VB, but rather to the "\" in VB. That is, it performs INTEGER
division. Since lFileReadCount is always smaller than fi.Length, it always
yields zero.

What VB does is a floating point division, so it gives a result of zero
dot something, which is then multiplied by 100, giving a value which is then
converted implicitly to integer when assigned to Progress.Value. You would
have spotted this last implicit conversion if the compilation of the VB
program used "Option Strict On".

If you want C# to do a similar operation as VB, you can do it like this:
Progress.Value =(int)(((double)lFileReadCount / (double)fi.Length) *
100);
 
J

Joe Cool

Hi Joe,

Did you specify the range of the Progress bar?
Check Maximum and Minimum and verify that Value isn't outside that range.

Remember, I am attempting to calculate a percentage, which should
range from 0 to 100. And the default maximum value of a progress bar
is 100.
 
J

Joe Cool

The "/" in C#, when aplied to two integer values, is not equivalent to
the "/" in VB, but rather to the "\" in VB. That is, it performs INTEGER
division. Since lFileReadCount is always smaller than fi.Length, it always
yields zero.

What VB does is a floating point division, so it gives a result of zero
dot something, which is then multiplied by 100, giving a value which is then
converted implicitly to integer when assigned to Progress.Value. You would
have spotted this last implicit conversion if the compilation of the VB
program used "Option Strict On".

If you want C# to do a similar operation as VB, you can do it like this:
Progress.Value =(int)(((double)lFileReadCount / (double)fi.Length) *
100);

PERFECT! Thank you.

My company is switching from VB to C#.NET so I am practising
converting some VB.NET apps I wrote for personal use. The more I use
C# the more I like it, but situations like this ain't helping!!!

VB does a HELL of a lot more implicit datatype conversions and it
seems I almost have to type EVERY conversion in C#.
 
J

Jon Skeet [C# MVP]

Joe Cool said:
PERFECT! Thank you.

My company is switching from VB to C#.NET so I am practising
converting some VB.NET apps I wrote for personal use. The more I use
C# the more I like it, but situations like this ain't helping!!!

VB does a HELL of a lot more implicit datatype conversions and it
seems I almost have to type EVERY conversion in C#.

Yes. This is a good thing, IMO - it makes it much clearer where
conversions are taking place, which means it's less likely to happen
without you knowing. As Alberto pointed out, with Option Strict On
you'd have had to do the conversion from floating point back to integer
in VB.NET too.

Not all conversions are explicit, of course, and the situation you've
got here is slightly different - there *is* an implicit conversion from
int to double - it's the types used for the *operation* which are
important. The C family of languages (from which C# derives) has always
made / do integer arithmetic when both of the operands are integers.

Note that you only need *one* of the casts to double in the division -
if either operand is a floating point one, floating point division will
be used instead of integer division.
 
A

Alun Harford

Joe said:
Hello, I am using VS2005. I am trying to convert a VB.NET app to
C#.NET. The VB app uses a progress meter to indiate how far a file has
been read. I use the following assignment statement in VB:

Progress.Value = (lFileReadCount / fi.Length) * 100

lFileReadCount is a Long that contains the current number of bytes
read. fi is a FileInfo object of the file being read. Progress is
shown as a percentage.

In C# the statement is:

Progress.Value = (lFileReadCount / fi.Length) * 100;

/ does integer division.
So this gets evaluated as (lFileReadCount / fi.Length) * 100 = 0 * 100=0

You could do horrible things converting to floats, or you could just
remember that instruction order matters.

Try:

Progress.Value = (lFileReadCount * 100) / fi.Length

Alun Harford
 
J

Jon Skeet [C# MVP]

Alun Harford said:
/ does integer division.
So this gets evaluated as (lFileReadCount / fi.Length) * 100 = 0 * 100=0

You could do horrible things converting to floats, or you could just
remember that instruction order matters.

Try:

Progress.Value = (lFileReadCount * 100) / fi.Length

Note that there's a potential problem with this, in that you end up
with temporary values which are larger. In this case, if lFileReadCount
is an int variable you will run into problems with files more than
~21MB, as at some point lFileReadCount will be greater than
int.MaxValue/100.

It's certainly a cleaner looking line than the version with floating
point though :)
 
A

Alun Harford

Jon said:
Note that there's a potential problem with this, in that you end up
with temporary values which are larger. In this case, if lFileReadCount
is an int variable you will run into problems with files more than
~21MB, as at some point lFileReadCount will be greater than
int.MaxValue/100.

The OP said it was a long. So you're nice and safe from overflow. :)

That means Progress.Value must take a long, which is odd, but the OP's
code would only compile if that were the case.

Alun Harford
 
J

Jon Skeet [C# MVP]

Alun Harford said:
The OP said it was a long. So you're nice and safe from overflow. :)

Ah, missed that bit.
That means Progress.Value must take a long, which is odd, but the OP's
code would only compile if that were the case.

Hmm. That is indeed very odd - presumably this isn't
System.Windows.Forms.ProgressBar then...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top