Help! Weird calculations on a dictionary

I just had the weirdest experience:

I have the following code which calculates the percentage of a value (amount stored in a DictAmount) and saves it to DictPercentage – except I ended up with negative percentages!

dictPercent.Value( position ) = Ceil( 100 * dictAmount.Value( position ) / DictSumAtPosition.Value( position ) ) // if it is 0 then stay zero, if it is more but less than 1 then round up to 1

To find out what was going on I added some variables:

[code]dim a as double = dictAmount.Value( position )
dim b as Double = DictSumAtPosition.Value( position )

dictPercent.Value( position ) = Ceil( 100 * dictAmount.Value( position ) / DictSumAtPosition.Value( position ) )

if dictPercent.Value( position ) < 0 then
break
end if[/code]

Sure enough the debugger breaks and the values are

a = 23164713,
b = 532854157,
dictPercent.Value( position ) = -3.0

It should be 4.3, not -3.0.

Now the weird thing (for me): If I comment out the line

dictPercent.Value( position ) = Ceil( 100 * dictAmount.Value( position ) / DictSumAtPosition.Value( position ) )  

and write instead

dictPercent.Value( position ) = Ceil( 100 * a / b)

then it works perfectly.

If I reverse it again I get negative values again.

Yet I can’t see anything wrong with the code.

Has anyone an idea what is happening here?

TiA

Markus

Maybe it is because a dictionary value is a variant… Have you tried

 dictPercent.Value( position ) = Ceil( 100 * Double(dictAmount.Value( position )) / Double(DictSumAtPosition.Value( position )) )

Might work, might not…

Dictionary.Value(key) returns a Variant. So you should use IntegerValue, SingleValue, or DoubleValue to make sure you get the right value back from the Variant.

This:

100 * dictAmount.Value( position )

… should be:

... 100 * dictAmount.Value( position ).DoubleValue ...

… and so on for all other.

I never ever use a value returned from a dictionary directly without:

  • assigning it to another non-Variant variable,
  • casting it, or
  • using one of the properties of Variant like DoubleValue or IntegerValue.

You should ALWAYS use a specific type accessor on a dictionary value

When you read from variant, better stuff it in local variable.
This way you can check the value in debugger and you are precise about whether to query double or integer from variant.

Thanks all, yes, that was it. Wish I could check you all :slight_smile:

Working now beautifully:

The only thing the compiler can use to determine what kind of math to use is “100”, an integer. So it’s going to do the whole thing in integer arithmetic. Evaluating left to right, you start with

100 * 23164713

which overflows to -1978495996.

You could try writing it as

100.0 * …

But it’s much better to be explicit when dealing with variants.

Going through all my value calls as we speak and changing them …