How to return integer part using backslash when dividing two decimals in Visual Basic

59 Views Asked by At

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

There are 3 best solutions below

10
jmcilhinney On BEST ANSWER

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.

0
Albert D. Kallal On

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.

0
dbasnett On

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