Skip to content

Instantly share code, notes, and snippets.

@speezepearson
Created April 8, 2014 18:03
Show Gist options
  • Save speezepearson/10164343 to your computer and use it in GitHub Desktop.
Save speezepearson/10164343 to your computer and use it in GitHub Desktop.
Stores floating-point numbers in log-space (intended for probability calculations).
from math import log, exp
from functools import total_ordering
@total_ordering
class LogFloat(object):
"""Represents a positive real number in log-space to avoid underflow."""
def __init__(self, normal=None, log_space=None):
if not ((normal is not None) ^ (log_space is not None)):
raise ValueError("must specify normal-space XOR log-space value")
self.logval = log(normal) if normal is not None else log_space
def __repr__(self):
return "LogFloat(log_space={!r})".format(self.logval)
def __str__(self):
return repr(self)
def __float__(self):
return float(exp(self.logval))
def __int__(self):
return int(float(self))
def __div__(self, other):
if isinstance(other, LogFloat):
return LogFloat(log_space=self.logval - other.logval)
result = float(self) / other
return LogFloat(result) if result>0 else result
def __rdiv__(self, other):
return LogFloat(other / float(self))
def __mul__(self, other):
if isinstance(other, LogFloat):
return LogFloat(log_space=self.logval + other.logval)
result = float(self) * other
return LogFloat(result) if result>0 else result
def __rmul__(self, other):
return self.__mul__(other)
def __pow__(self, power):
return LogFloat(log_space=self.logval * power)
def __rpow__(self, base):
return base ** exp(self.logval)
def __add__(self, other):
result = float(self) + other
return LogFloat(result) if result>0 else result
def __radd__(self, other):
result = other + float(self)
return LogFloat(result) if result>0 else result
def __sub__(self, other):
result = float(self) - other
return LogFloat(result) if result>0 else result
def __rsub__(self, other):
result = other - float(self)
return LogFloat(result) if result>0 else result
def __lt__(self, other):
if isinstance(other, LogFloat):
return self.logval < other.logval
return exp(self.logval) < other
def __eq__(self, other):
if isinstance(other, LogFloat):
return self.logval == other.logval
return exp(self.logval) == other
def __abs__(self):
return self
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment