CodeIQ:オーバーフローに気をつけて

私自身が表題の問題を解いた時のプログラムについて解説します。
問題の詳細は「オーバーフローに気をつけて」(CodeIQ)を参照してください。

問題の概要

問題の解説です。f(x, y, z) = pow(x, pow(y, z)) を、x,y,zいずれも1より大きい実数(x>1, y>1, z>1)とおいたとき、与えられたx,y,zの複数の組合せの中で、f(x, y, z)が最大となる組合せの番号を求めるプログラムを実装してください。
※ f(x, y, z)を数式で書くとxyzです。
【入力】
1.1,1.2,1.3
4.5,6.7,9.8

【出力】
1
※ 番号は0始まりのようです。

私のプログラム

Pythonで解答しています。

#!/usr/local/bin/python3
# -*- coding: utf-8 -*-

import fileinput
import math

if __name__ == "__main__":
	vals = []
	logvs = []
	max_no = -1
	max_val = float("-inf")

	for line in fileinput.input():
		if not line.strip():
			continue

		vals.append(list(map(float, line.split(","))))

	for i, xyz in enumerate(vals):
		v = math.log(math.log(xyz[0])) + xyz[2] * math.log(xyz[1])
		logvs.append(v)
		if v > max_val:
			max_val = v
			max_no = i

	print("%d" % max_no)

解説

これはプログラムの問題というより数学の問題でしょうか?

対数

こう言う巨大な数字を扱う場合の基本的なテクニックは対数を使うことです。なので元の式に対数をとって変形した式で計算します(72行目)。2回対数を取ればオーバーフローせずに計算できるようになります。
後は入力値の中で最も大きい値をループで探すだけです。

雑感

「こんなの対数で計算すれば終わり」と余裕で始めたのですが、2回対数をとった時の式の変形の仕方を忘れていて妙に苦労しました。