0

I am trying to divide two decimals and want to get the exact integer part of the result only using a\b. Consider the following example:

        Dim a, b As Integer
        a = 200
        b = 2

        Writeline(Math.Log(a) / Math.Log(b))
        Writeline(Math.Log(a) \ Math.Log(b))

On (Math.Log(a) / Math.Log(b) I am getting 7.64385619 and I was expecting to get 7 with Math.Log(a) \ Math.Log(b) but instead its returning 5. What should I do to return 7 instead of 5? How am I getting 5 there? When dealing with whole numbers it works fine. I tried to look on the internet but could not get a solution. Probably its my search phrasing.

3 Answers 3

4

This is a perfect example of why you should ALWAYS read the relevant documentation. Here is the documentation for the integer division operator. It says this:

Before performing the division, Visual Basic attempts to convert any floating-point numeric expression to Long. If Option Strict is On, a compiler error occurs. If Option Strict is Off, an OverflowException is possible if the value is outside the range of the Long Data Type. The conversion to Long is also subject to banker's rounding.

You clearly have Option Strict Off, or else your code wouldn't even compile. That's a bad thing from the start. With Option Strict Off in your case, 5.2983173665480363 and 0.69314718055994529 are rounded to 5 and 1 respectively. 5 \ 1 is 5, which is the result you're seeing.

What that means is that you cannot use integer division in this case. You will need to use regular division and then call Math.Floor or Math.Truncate to remove the fractional part.

Sign up to request clarification or add additional context in comments.

10 Comments

Thank you. So there is no other solution, other than creating my own function to achieve my objective.
don't bother trying to use the \ to force integre math - it's confusing on how it works. See my post below - just do the math, and then round how you want, and life is all good.
@maponda1, you don't necessarily have to write your own function. Where you have Math.Log(a) \ Math.Log(b), just use Math.Floor(Math.Log(a) / Math.Log(b)) instead. Of course, if integer division with logs is something you're doing a lot, you probably ought to write your own function anyway, even without this extra requirement.
@maponda1, also note that integer will division will always produce an integer type; Long in your original case. Math.Floor will produce an integer value but the type will still be floating-point. If you need an integer type then you'll have to convert that result. Of course, if you leave Option Strict Off then that's likely not an issue. You definitely shouldn't do that though. ALWAYS set Option Strict On except in the very rare cases where you specifically require late binding. Set it On in the project properties and in the VS options, so it's On by default in future.
Option strict is not all that bad of a choice. The cost + time of having to constant cast expressions in most cases is not worth the extra effort. After all, this was tagged as asp.net, and in web land, just about all elements you work with are strings, and JavaScript like the defaults in vb.net are thus not strong typed. Last time I looked JavaScript by a HUGE margin is the most popular language in our industry - guess what, it also auto casts all the time. So, this debate about strong typed language vs not strong typed? Guess which development paradigm in our industry won, and won by huge??
|
0

There is a System.Math method that can be used to emulate what the integer division operator does. e.g.

Option Strict On

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim a, b As Integer
        a = 200
        b = 2
        Dim logA As Double = Math.Log(a)
        Dim logB As Double = Math.Log(b)
        Debug.WriteLine(logA / logB)
        Debug.WriteLine(Math.Truncate(logA / logB)) 'truncate is what \ does
    End Sub
End Class

Comments

0

Actually, even with options strict on or off, you still going to have issues.

I would not worry, and just do a round (rounds up), or floor (removes the decimal part).

Hence, I would use this:

    Dim a, b As Integer
    a = 200
    b = 2

    Debug.Print(Math.Floor(Math.Log(a) / Math.Log(b)))

I would not bother or mess with using "\" trying to force integer math here.

So, what is actually going on?

Well, you have this:

Math.Log(a) \ Math.Log(b)

Which becomes this:

       (5.29831736654804 \ 0.693147180559945)

and with the "back slash", and force to integer?

Then the values are converted BEFORE the divide occurs. So, we have this now:

       (5 \ 1)

THEN the divide occurs and we get 5.

You can turn off automatic casting, and force strong typing, but you WILL STILL get the same answer - the one you NOT looking for.

So, this fails due to using the "convert to integers" BEFORE we divide here (the "\" option).

You want to divide the 2 numbers and THEN convert to integer.

So, just let a "normal" divide occur and do NOT convert the 2 values to integers BEFORE we divide them. You looking to do a plain Jane regular divide and then drop the fractional part. So, what you looking for is a VERY different goal here, and one in which we don't want to convert EACH number to integer BEFORE we do the divide.

So, using a "regular" decimal divide, then we get this:

      (5.29831736654804 / 0.693147180559945)

Then this:

  (7.643856189774732)

And then we want either:

   Math.Round(7.643856189774732)

Which gives 8,

Or we want

  Math.Floor(7.643856189774732)

Which gives 7 (it does not round up).

So, allow the expression to have "regular" decimal math, and then chop off the decimal (fraction) part AFTER the plain Jane good old fashion division occurs here. As noted, the "\" does NOT JUST return an integer result, but converts BOTH values to integer BEFORE the divide occurs, and that is a Mount Everest of a different issue, and one you did not expect. And what is worse, that converting to integer also will round up or down based expression being > 0.5 for the decimal part.

So, not only are the 2 expressions being converted to integer, but EVEN WORSE is the 2 expressions will round up or down BEFORE the divide occurs!!! So "\" does MUCH MORE then just say produce an integer result, it ALSO converts the two values to integers, and uses up or down rounding before the divide!

This of course can be handy if that's what you looking to achieve, and in this case you are not.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.