Math Question

Oorang

Well-known Member
Joined
Mar 4, 2005
Messages
2,071
This may be the dumbest question ever but I can't remember how to do this and all the sites that cover exponentiation do not speak to it. How do you solve for X in the following? I mean I could just put up a loop that would count how many times 2187will divide by 3, but I thought there was a better way.
3^X = 2187
 

Excel Facts

When they said...
When they said you are going to "Excel at life", they meant you "will be doing Excel your whole life".
3^X = 2187
LOG(3^X) = LOG(2187)
X*LOG(3) = LOG(2187)
X = LOG(2187)/LOG(3)
X = 7
 
Upvote 0
Wow Oaktree nice kungfu. I read up on logarithims and their implementation in VBA and I now realize that this is going to be one of those time a pure math solution is actually slower. I have a decimal number 0-127 that represents days of the week Sun-Sat with Sun as the MSD and Sat as the LSD. I have been using bitwise comparisons to pull out any given day from that number Ex:
Code:
    bytWkClmn = (7 - VBA.Weekday(dtEval, vbSunday))
    blnIsInWeeks = ((2 ^ bytWkClmn) And bytWeeks) = (2 ^ bytWkClmn)
But in a different function I wanted to check to see if it had one and only one day and if so convert that day to a Weekday Sun-Sat 1-7. I think that fastest implementation (in terms of processing time) is NOT going to be to check the exponent, I think it's going to be this:
Code:
        bytWeekday = VBA.Switch(bytWeek = 64, 1, bytWeek = 32, 2, bytWeek = 16, 3, bytWeek = 8, 4, bytWeek = 4, 5, bytWeek = 2, 6, bytWeek = 1, 7)
        If Not CBool(bytWeekday) Then Exit Function
 
Upvote 0
Suit yourself, but it seems to me that:

Code:
bytWeekday = VBA.Switch(bytWeek = 64, 1, bytWeek = 32, 2, bytWeek = 16, 3, bytWeek = 8, 4, bytWeek = 4, 5, bytWeek = 2, 6, bytWeek = 1, 7)

is longer than:

Code:
bytWeekday = 7-(Log(bytWeek)/Log(2))

;-)
 
Upvote 0
Well you got me there... Almost :-)
I need to determine that the number is only an extact power of 2. Otherwise more than one day has been selected. (And in the context of this function, that would be an invalid argument.) So there are 2 issues. 1st, log is not returning exact values, just very close values. The inherent type-conversion of putting the formula result into a byte conceals this a bit, but when you go to test to make sure you hade only a power of 2, you notice :-D The other issue is that the log function generates an error when you feed it a 0. I couldn't out how to use log without a zero test and even if I used a zero test I would still need to figure out if it was a power of 2 or not. The only solution I saw was the one I posted, however, based on your impressive posts so far, I am very open to suggestions. (I can see I need to progress a bit in my math) :lol:
This:
Code:
Sub TestLog()
    Dim x As Byte
    Dim l As Double
    Dim i As Byte
    Do
    l = 7 - (VBA.Log(x) / VBA.Log(2#))
    Debug.Print x, l, CInt(l), l = CInt(l)
    x = 2 ^ i
    i = i + 1
    Loop Until x > 64
End Sub
Returns this:
0 0 0 True
1 7 7 True
2 6 6 True
4 5 5 True
8 4 4 True
16 3 3 True
32 2 2 False
64 1 1 False


*Edit: see altered test code and output.
 
Upvote 0
Since: if 2^n = x, then (some algebra goes here) n = log(x)/log(2)

Therefore, if log(x)/log(2) is an integer, n is an integer, so x is an exact power of 2. As such, a simple test of Int(log(x)/log(2)) = log(x)/log(2) [perhaps rounded to account for floating point oddities] would suffice to check for whether x is an exact power of 2.

(In your example, if x = 4, you're testing log(4+1)/log(2), and, since 5 is not an exact power of 2, you're getting a decimal.) edit: I see you've changed the code to be log(x) instead of log(x+1)

You are correct, though, that you'd need a separate test if x = 0, as log(0) is undefined (technically, lim n-->infinity of 2^-n = 0, but you get my point). Then again, if you're interested in exact powers of 2, couldn't you just ignore the case if x = 0?
 
Upvote 0
Well the point that I don't think I have quite made yet is best described by the issue of properly detecting integer output. I think the following describes it quite nicely. It SHOULD output 0. It does not.
Code:
Sub DoesNotEqual2()
    Dim x As Integer
    Dim l As Double
    x = 32
    l = 7 - (VBA.Log(x) / VBA.Log(2#))
    Debug.Print l, CInt(l), l - CInt(l), l = CInt(l)
End Sub
 
Upvote 0
Yep, chalk that one up to floating point arithmetic.

This produces 0 though ;-)

Code:
Sub DoesNotEqual2()
Dim x As Integer, l As Single
    x = 32
    l = 7 - (VBA.Log(x) / VBA.Log(2#))
    Debug.Print l - CInt(l)
End Sub
 
Upvote 0
Nice :-) You do amaze :-) But now we are up to 3 math operations, 2 function calls and at least 1 type conversion and of course the 0 test and the post test. (Could the lords a leaping be far behind?) :lol: So while the log solution is way cooler, I fear I am over-engineering the problem. I think I probably should use the Switch function to keep whoever ends up maintaining this code from committing sepukku. (Remember maintainable code saves lives, and the life you save just might be your own ;) )

Edit:
This is taking into account that the full task is: Convert bytWeeks into a day of the week and store it for further use. Make sure 1 (and only 1) day is selected. Make sure that one selected day is equal to the weekday of dtEval.

Further Edit:
But I can't over-emphasize how much I appreciated your help, because it cued me into a few things for which I can already see future application.
 
Upvote 0
I guess it depends on what the rest of your code will be doing.

Code:
bytWeekday = VBA.Switch(bytWeek = 64, 1, bytWeek = 32, 2, bytWeek = 16, 3, bytWeek = 8, 4, bytWeek = 4, 5, bytWeek = 2, 6, bytWeek = 1, 7)

is clearly manageable, so long as your other tests handle numbers not in that list (like 63).

At the end of the day, it's your code, so you should choose whichever method you're most comfortable with. After all, we all know you'll be the one getting questions about it 5 years from now, long after you've forgotten all about this project. ;-)
 
Upvote 0

Forum statistics

Threads
1,225,229
Messages
6,183,728
Members
453,185
Latest member
radiantclassy

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top