Jump to content

NumConvertBase UDF


therks
 Share

Recommended Posts

Updates:

  • Changed function name to NumBaseConvert. Also, now supports real numbers, not just integers.
  • Updated the function a little. Realized that if the baseFrom is 10, there's no need to convert it to decimal first, as it's already there. So if baseFrom is set to 10, then the convert to decimal step is skipped completely. It shaves off a bit of time.
  • Fixed something that Valik considered a bug (line 69 of NumBaseConvert.au3). Don't want this bug being fixed and then the UDF doesn't work.
Original Post:

I don't know if anybody here has ever had need for a function like this, but I have in the past. So I figured I'd take the plunge as it were and write it up. I wrote up a function to do this in PHP in the past, and it was rather easy.. I must have gotten dumber in the interim because it took me about half an hour to stumble through the math last night.

UDF Header:

CODE
;===============================================================================

;

; Description: _NumBaseConvert - Convert a number from one base to another.

; ie: Convert decimal (base 10) to octal (base 8), or hexadecimal

; (base 16) to binary (base 2).

; Syntax: _NumBaseConvert( $v_Input, $i_BaseFrom, $i_BaseTo )

; Parameter(s): $v_Input - Number to convert, can be an integer or a string

; (if 'BaseFrom' is higher than 10).

; $i_BaseFrom - Number base to convert from. Converted to integer

; within function. Cannot be lower than 2, or higher than 36.

; $i_BaseTo - Number base to convert to. Converted to integer

; within function. Cannot be lower than 2, or higher than 36.

; Return Value(s): On Success - String of the converted number.

; On Failure:

; - $i_BaseFrom < 2 or > 36 : Returns false, @error set to 1

; - $i_BaseTo < 2 or > 36 : Returns false, @error set to 2

; - Invalid character in $v_Input : Returns false, @error set to 3

; Author(s): Saunders (rksaunders@gmail.com)

;

;===============================================================================

NumBaseConvert.zip

Edited by Saunders
Link to comment
Share on other sites

Oooooo... time for an enterprising college student to create the AutoIt RPN calculator demo...

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

I didn't know about that post, but no, actually I meant a virtual calculator with a fancy GUI.

Dale

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

Also accept non integers.

http://www.autoitscript.com/forum/index.php?showtopic=7282

<{POST_SNAPBACK}>

I'll be honest, I really don't have a clue how to convert beyond integers. I'll see what I can do though.

Edit: Wow this stuff is confusing. I've been reading Wikipedia and other places for about an hour now, and I just can't figure it out. The only thing I can arrive at is that converting any floating point numbers is going to be logically skewed, you'll never get a perfect conversion. But I can still implement the same type of conversion you're using. So I guess that's what I'll do.

Edited by Saunders
Link to comment
Share on other sites

Wikipedia math sometime have little mistakes or imprecision.

Anyway, the idea is simple, since every number is the sum of its digits*base^position (starting from 0)

a non iteger have values where position is negative.

Link to comment
Share on other sites

I'll be honest, I really don't have a clue how to convert beyond integers. I'll see what I can do though.

<{POST_SNAPBACK}>

Here is how to convert decimal 42.3125 to binary:

42 in base 10 = 101010 in binary

.3125 * 2 = 0.6250 (note integer part, copy fractional part down)

.6250 * 2 = 1.2500 (repeat until fractional part = 0)

.2500 * 2 = 0.5000

.5000 * 2 = 1.0000 (stop!)

Reading downwards, .3125 in base 10 = .0101 in binary

Therefore, decimal 42.3125 = 101010.0101 in binary

You already know how to convert the integer part from any base to base 10 to any base -- using the above you can convert fractions from base 10 to any base (simply multiply by the base instead of 2).

Converting binary .0101 to decimal:

.0101 = 0(2^-1) + 1(2^-2) + 0(2^-3) + 1(2^-4)

= 0(0.5) + 1(0.25) + 0(0.125) + 1(0.0625)

= .3125

This example can be adapted to change a fraction of any number base to decimal.

Edit: one problem you most definitely will come across is that when converting a fraction to another base, most numbers will result in a neverending stream of digits. Take for instance the base 7 number 0.1 which equates to a seventh in decimal terms, which is 0.142857142857. You may wish to program some logic to limit the number of digits processed which will in turn slightly decrease the number's accuracy (as you mentioned in your last post anyway).

Edited by LxP
Link to comment
Share on other sites

Hey thanks for the info guys, especially you LxP. That was a lot easier to understand than the Wikipedia stuff. And ezzetabi, I noticed their math was a little off.. what was that one part... Oh here:

hex 129

d1=1 d2=2 d3=9 base=16

d1 * base + d2 * base + d3= 1 * 16 + 2 * 16 + 9= decimal 297

Either I didn't understand it.. or it's wrong. But as near as I know, 1 * 16 + 2 * 16 + 9 = 57. Not 297.

Anyway, I'll make sure to copy this information down, LxP, and modify my function. Thanks again!

Edited by Saunders
Link to comment
Share on other sites

Glad to help, Saunders -- even more glad to find that that knowledge actually has proven itself useful now! :)

hex 129

d1=1 d2=2 d3=9 base=16

d1 * base + d2 * base + d3= 1 * 16 + 2 * 16 + 9= decimal 297

Either I didn't understand it.. or it's wrong. But as near as I know, 1 * 16 + 2 * 16 + 9 = 57. Not 297.

I think that this example was designed to work on a calculator (i.e. evaluated at each number without regard to operator precedence).

(((1 × 16 = 16) + 2 = 18) × 16 = 288) + 9 = 297

The best way to look at it (I believe, and as ezzetabi wrote earlier) is like this:

129 in base 16

= 1(16^2) + 2(16^1) + 9(16^0)

= 256 + 32 + 9

= 297

Link to comment
Share on other sites

I think that this example was designed to work on a calculator (i.e. evaluated at each number without regard to operator precedence).

Ah I see, so it's like they'd never heard of BEDMAS. :)

On topic, I almost had the function complete, when I ran into a really odd snag.

I was doing this

_NumBaseConvert(0.3125, 10, 2) and it was returning something like 0.00000000000000101. Turned out it was a bug (or should I say feature?). I submitted it here, but I guess it's a limitation or something. Seems odd to me either way. Guess I'll just have to frig around with the calculation a little more.

Oh, and while I'm here. What name works better? NumBaseConvert? or NumConvertBase? I'm trying to keep with the AutoIt naming scheme, but I'm used to BaseConvert in another program and kept typing it when I was testing the function, so I'm tentatively using that form right now. Plus the AutoIt naming scheme is based on the whole ([subject] [Operation]) so it could be like ([Number] [Convert Base]) or ([Number Base] [Convert]). I'd love to just use _BaseConvert(), but that screws everything up. Anyway, comments, suggestions?

Edited by Saunders
Link to comment
Share on other sites

0.00000000000000101 in base two is about 0.00003814697265625 [ that is (1/2^15) + (1/2^17) ] in base ten... something is wrong.

If it is not a bug probably something is wrong in your code.

I have a question, not to brag about my code, but since I already done it why do not use my implementation? If you want a real _any2any converter just use the two function altoghter like _Dec2Any(_Any2Dec())...

Link to comment
Share on other sites

Oh, and while I'm here. What name works better? NumBaseConvert? or NumConvertBase?

Personally I would prefer NumBaseConvert().

Edit: according to my calculations 0.3125 in decimal should equal 0.0101 in binary.

Edited by LxP
Link to comment
Share on other sites

Damn I kind of forgot about this whole thing..

The last couple days, my computer was throwing a fit (read the July 28 post) on me and I completely forgot about this. I actually have the function ready to go though, and it does appear to be faster.

<{POST_SNAPBACK}> Updated the first post with the attachment.

Edited by Saunders
Link to comment
Share on other sites

Does this look right? I was fooling around with the number 1010.0101 in binary. Then on a whim I set it to decimal, but to convert to binary, and got this:

Decimal: 1010.0101

Binary: 1111110010.00000010100101011110100111100001101100001000100110100000001

Is that right? Or is my function still glitched?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...