0
import math
def hexToDec(hexi):
    result = 0
    for i in range(len(hexi)-1,-1,-1):
        if hexi[i] == 'A':
            result = result + (10 * math.pow(16,i))
        elif hexi[i] == 'B':
            result = result + (11 * math.pow(16,i))
        elif hexi[i] == 'C':
            result = result + (12 * math.pow(16,i))
        elif hexi[i] == 'D':
            result = result + (13 * math.pow(16,i))
        elif hexi[i] == 'E':
            result = result + (14 * math.pow(16,i))
        elif hexi[i] == 'F':
            result = result + (15 * math.pow(16,i))
        else:
            result = result + (int(hexi[i]) * math.pow(16,i))
    return result

Even after reversing the range order and reimporting I still get the same results.

devnull
  • 118,548
  • 33
  • 236
  • 227
user3243566
  • 3
  • 1
  • 2
  • 1
    Why isn't `int(hexi,16)` cut it? It seems to be able to handle huge numbers in py3. (Perhaps `long(hexi,16)` works in py2?) – Jonas Byström Jan 28 '14 at 08:25

7 Answers7

1

While there can be beautiful answers like this

x = int("FF0F", 16)

It's also important to see how the original code went wrong. The corrected version should be:

import math
def hexToDec(hexi):
    result = 0
    for i in range(len(hexi)):
        cur_pow = len(hexi) - i  - 1
        if hexi[i] == 'A':
            result = result + (10 * math.pow(16,cur_pow))
        elif hexi[i] == 'B':
            result = result + (11 * math.pow(16,cur_pow))
        elif hexi[i] == 'C':
            result = result + (12 * math.pow(16,cur_pow))
        elif hexi[i] == 'D':
            result = result + (13 * math.pow(16,cur_pow))
        elif hexi[i] == 'E':
            result = result + (14 * math.pow(16,cur_pow))
        elif hexi[i] == 'F':
            result = result + (15 * math.pow(16,cur_pow))
        else:
            result = result + (int(hexi[i]) * math.pow(16,cur_pow))
    return result

Whether you loop in "reverse" or not, the power order and the index to hexi should iterate at the opposite direction, one increasing another decreasing.

Now you can forget about this and use the answers suggested by others.

YS-L
  • 14,358
  • 3
  • 47
  • 58
  • +1 for using the for loop like the op wanted. – Kobi K Jan 28 '14 at 08:36
  • I'd have improved it by using `+=` a lot. – Alfe Jan 28 '14 at 10:05
  • And casing each letter is obviously not the best way to do it, even if you leave the loop idea unchanged. `result += (ord(hexi[i]) - ord('A') + 10) * (16 ** cur_pow)` (or even `…<< (4 * cur_pow)`) woudl further improve that solution ;-) – Alfe Jan 28 '14 at 10:09
  • Well, these points are definitely valid, and have been well addressed by other great answers. I'm trying to point out the logical error which the OP is facing and could not figure out -- isn't this the real question? ;-) – YS-L Jan 28 '14 at 10:14
  • Thank you for this answer. I needed it with a for loop because my teacher wanted to teach us a combination of looping through strings and converting number systems. I don't think this question is a duplicate because of this. – user3243566 Jan 29 '14 at 22:03
0

In python if you want to re-import something, you need to restart the python process, or manually copy past the content of the file you've changed in python, or more conveniently using ℅cpaste in ipython.

Re-import doesn't work in python the way you are expexting.

adrin
  • 4,511
  • 3
  • 34
  • 50
0

Too many elif, pow... Just shift (result = result * 16) and add (ord(ch) - ord(...)) something like

""" Manual hexadecimal (string) to decimal (integer) conversion
    hexadecimal is expected to be in uppercase
"""
def hexToDec(hexi):
  result = 0;

  for ch in hexi:
    if 'A' <= ch <= 'F':
      result = result * 16 + ord(ch) - ord('A') + 10
    else:
      result = result * 16 + ord(ch) - ord('0')

  return result;
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
0

did you observe the indexes generated by your for loop ?

whatever the direction you take for scanning the input string (forward or backward), the indexes generates 0 for the leftmost digit and len(i)-1 for the rightmost. so when you use the index to compute the "digit place" in math.pow(16,i), you are computing as if the first character of the input string is the rightmost (least significant) digit.

try using math.pow(16, len(hexi)-1-i)...

after making this correction, the scanning direction (forward or backward) does not matter. you can rewrite your for loop as for i in range(len(hexi)):.

also, do you know that you don't need to import the math module to compute powers ? you can use the ** operator: 2**4, 16**i, 16**(len(hexi)-1-i)

Adrien Plisson
  • 22,486
  • 6
  • 42
  • 73
0
hexToDec = lambda hexi: int(hexi,16)

or in Python 2:

hexToDec = lambda hexi: long(hexi,16)

?

Jonas Byström
  • 25,316
  • 23
  • 100
  • 147
0

Others have show the fast way to do it but since you wanted it in a for loop...You problem is in your loop parameters, the power needs to be len of the string - the current place - 1 Just like @YS-L did in his answer also instead of using if-else you have dictionary! (you can also check for 'A' <= myCurrentChar <= 'F' instead)

import math
def hexToDec(hexi):
    result = 0
    convertDict = {"A": 10, "B": 11, "C": 12, "D": 13, "E": 14, "F": 15}
    for i in range(len(hexi)):    
        if str.isdigit(hexi[i]):
            result += int(hexi[i]) * math.pow(16, len(hexi) - i - 1)
        else:
            result += convertDict[hexi[i]] * math.pow(16, len(hexi) - i - 1)

    return int(result)

print hexToDec("FFA")

Output:

4090
Kobi K
  • 7,743
  • 6
  • 42
  • 86
0

One-liner - (not very readable) - but works for lower case and handles 0x prefix

sum(16**pwr*(int(ch) if ch.isdigit() else (ord(ch.lower())-ord('a')+10))
    for pwr, ch in enumerate(reversed(hexi.replace('0x',''))))
volcano
  • 3,578
  • 21
  • 28