0

I have a range of numbers in (0, 1]

I would like to take the natural log of these numbers, and then store as 8.8 fixed point.

My foruma is K*ln(x) + (1<<16)

but I am not sure what the best value is for K .

My thinking is that if x doubles, then ln(x) increases by ln(2), so the fixed point value should increase by 1 in fixed point (i.e. 256)

So, this would mean K = 256/ln(2)

Does this make sense?

Jacko
  • 12,665
  • 18
  • 75
  • 126
  • 1
    Would that be [Q8.8](https://en.wikipedia.org/wiki/Fixed-point_arithmetic#Notation) as in 16 bit quantity with 8 bit integer and 8 bit fractional part? Is the `(1 << 16)` meant to convert the negative numbers to positive ones? As you are aware, `ln(0)` is essentially negative infinity, so if most of your numbers are from the (0, 0.01] range, you'd probably pick a different scale than if most were from the (0.9, 1] range. Do you have details on the distribution or similar information to decide which information you'd rather loose? – MvG Oct 12 '16 at 17:30
  • Thanks. Yes, Q8.8 it is.But, I am not sure what kind of distribution the range of numbers follows. – Jacko Oct 14 '16 at 00:57
  • Some example inputs and expected results would help clarify. – chux - Reinstate Monica Oct 14 '16 at 03:44

1 Answers1

1

As x approaches 0, ln(x) will diverge to negative infinity. So you are essentially trying to map an infinite domain to a finite range.

If you do so in a linear way, you have to cut off at some point. If you choose your cut-off at too low a value, you'll be wasting precision for the numbers you represent. If you choose to high a cut-off, too many values will be clamped to the minimal element of the range. Without knowledge about the distribution of the point, it will be very hard to guess a suitable balance here.

So perhaps you could apply a non-linear map instead of the linear one you proposed. Something like the exponential function? Which would mean you'd actually store x instead of ln(x). So I'd say if you want to store values from [0,1) in 16 bit without too much loss of information, you'd just use Q0.16, i.e. all the digits in the fractional part. For (0,1] you can either store 1 − x or do a special case for x = 1 so that you encode that as 0 instead. If you have Q8.8 numbers, you'd multiply your numbers by 28 = 256 first, but if you have access to the bit representation that multiplication would be a waste of time.

I guess you had a reason you'd want to store logarithms, so this answer may not be what you were hoping for. I don't see an easier way around the underlying problem, though, so you may have to reconsider some of your ideas.

MvG
  • 57,380
  • 22
  • 148
  • 276