普通文本  |  66行  |  1.45 KB

"""fontTools.misc.fixedTools.py -- tools for working with fixed numbers.
"""

from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *

__all__ = [
    "fixedToFloat",
    "floatToFixed",
]

def fixedToFloat(value, precisionBits):
	"""Converts a fixed-point number to a float, choosing the float
	that has the shortest decimal reprentation.  Eg. to convert a
	fixed number in a 2.14 format, use precisionBits=14.  This is
	pretty slow compared to a simple division.  Use sporadically.
	
	>>> fixedToFloat(13107, 14)
	0.8
	>>> fixedToFloat(0, 14)
	0.0
	>>> fixedToFloat(0x4000, 14)
	1.0
	"""

	if not value: return 0.0

	scale = 1 << precisionBits
	value /= scale
	eps = .5 / scale
	digits = (precisionBits + 2) // 3
	fmt = "%%.%df" % digits
	lo = fmt % (value - eps)
	hi = fmt % (value + eps)
	out = []
	length = min(len(lo), len(hi))
	for i in range(length):
		if lo[i] != hi[i]:
			break;
		out.append(lo[i])
	outlen = len(out)
	if outlen < length:
		out.append(max(lo[outlen], hi[outlen]))
	return float(strjoin(out))

def floatToFixed(value, precisionBits):
	"""Converts a float to a fixed-point number given the number of
	precisionBits.  Ie. int(round(value * (1<<precisionBits))).

	>>> floatToFixed(0.8, 14)
	13107
	>>> floatToFixed(1.0, 14)
	16384
	>>> floatToFixed(1, 14)
	16384
	>>> floatToFixed(0, 14)
	0
	"""

	return int(round(value * (1<<precisionBits)))


if __name__ == "__main__":
    import doctest
    doctest.testmod()