0

I need to use a module that does some math on integers, however my input is in floats.

What I want to achieve is to convert a generic float value into a corresponding integer value and loose as little data as possible.

For example:

val : 1.28827339907e-08
result : 128827339906934

Which is achieved after multiplying by 1e22.

Unfortunately the range of values can change, so I cannot always multiply them by the same constant. Any ideas?

ADDED
To put it in other words, I have a matrix of values < 1, let's say from 1.323224e-8 to 3.457782e-6.

I want to convert them all into integers and loose as little data as possible.

Michal
  • 6,411
  • 6
  • 32
  • 45
  • What is the correspondence? Removing the decimal point and the exponent? – Joni Sep 05 '13 at 14:10
  • The data is already lost; there is no way to determine what the original intended value was. – Ignacio Vazquez-Abrams Sep 05 '13 at 14:12
  • @Joni Simply put, yes. – Michal Sep 05 '13 at 14:12
  • @IgnacioVazquez-Abrams I know that it's impossible to preserve the exact values, that's why I wrote "loose as little data as possible" – Michal Sep 05 '13 at 14:13
  • Well if you have it in exponent form how about you store it in two variables? `result = (128827339906934, 8)`. You know that it's in exponent form so that is representing 1.28827339906934e-08 – Michael Aquilina Sep 05 '13 at 14:15
  • The thing of it is that there is *no way* to figure out which part of the data is important; an algorithm may result in `128827339906934`, but it missed the "357" after it. – Ignacio Vazquez-Abrams Sep 05 '13 at 14:20
  • Dealing with floating point representation errors is always tricky so I would say just take arbitrary number y (1e10 for example) for each number x take int(x * y), and after all estimate computation error. Pretending that you can get more information that you really have won't get you closer to the real solution. – zero323 Sep 05 '13 at 14:29
  • What about values greater than MAX_INT? – RickyA Sep 05 '13 at 14:36
  • @RickyA That's why I'm not so eager to multiply values by a huge constant. – Michal Sep 05 '13 at 14:38
  • 1
    Well in python if you exceed an integers capacity it is automatically converted to a long. Try the following in a console: `i = 2343`. if you check type(i) you will see it is an `int`. If you then reassign i as `i = i * 100000000000000000` you will see type(i) is now a `long`. In general, you should not really worry about the [capacity of numbers in python](https://mail.python.org/pipermail/tutor/2003-July/023803.html). – Michael Aquilina Sep 05 '13 at 21:03

4 Answers4

2

If you want to preserve the values for operations on matrices I would choose some value to multiply them all by.

For Example:

1.23423
2.32423
4.2324534

Multiply them all by 10000000 and you get

12342300
23242300
42324534

You can perform you multiplications, additions etc with your matrices. Once you have performed all your calculations you can convert them back to floats by dividing them all by the appropriate value depending on the operation you performed.

Mathematically it makes sense because

(Scalar multiplication)
M1` = M1 * 10000000   
M2` = M2 * 10000000

Result = M1`.M2`
Result = (M1 x 10000000).(M2 x 10000000)
Result = (10000000 x 10000000) x (M1.M2)

So in the case of multiplication you would divide your result by 10000000 x 10000000.

If its addition / subtraction then you simply divide by 10000000.

You can either choose the value to multiply by through your knowledge of what decimals you expect to find or by scanning the floats and generating the value yourself at runtime.

Hope that helps.

EDIT: If you are worried about going over the maximum capacity of integers - then you would be happy to know that python automatically (and silently) converts integers to longs when it notices overflow is going to occur. You can see for yourself in a python console:

>>> i = 3423
>>> type(i)
<type 'int'>
>>> i *= 100000
>>> type(i)
<type 'int'>
>>> i *= 100000
>>> type(i)
<type 'long'>

If you are still worried about overflow, you can always choose a lower constant with a compromise for slightly less accuracy (since you will be losing some digits towards then end of the decimal point).

Also, the method proposed by Eric Postpischil seems to make sense - but I have not tried it out myself. I gave you a solution from a more mathematical perspective which also seems to be more "pythonic"

Michael Aquilina
  • 5,352
  • 4
  • 33
  • 38
2

The answers that suggest multiplying by a power of ten cause unnecessary rounding.

Multiplication by a power of the base used in the floating-point representation has no error in IEEE 754 arithmetic (the most common floating-point implementation) as long as there is no overflow or underflow.

Thus, for binary floating-point, you may be able to achieve your goal by multiplying the floating-point number by a power of two and rounding the result to the nearest integer. The multiplication will have no error. The rounding to integer may have an error up to .5, obviously.

You might select a power of two that is as large as possible without causing any of your numbers to exceed the bounds of the integer type you are using.

The most common conversion of floating-point to integer truncates, so that 3.75 becomes 3. I am not sure about Python semantics. To round instead of truncating, you might use a function such as round before converting to integer.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

Perhaps consider counting the number of places after the decimal for each value to determine the value (x) of your exponent (1ex). Roughly something like what's addressed here. Cheers!

Community
  • 1
  • 1
gromiczek
  • 2,970
  • 5
  • 28
  • 49
0

Here's one solution:

def to_int(val):
    return int(repr(val).replace('.', '').split('e')[0])

Usage:

>>> to_int(1.28827339907e-08)
128827339907
Joni
  • 108,737
  • 14
  • 143
  • 193
  • This is a less nice way of doing what Michael Aquilina suggested. If you were to try this with 1.2e-08 and 1.23e-07 and then operate on the new values, the second value would be larger than the first. There is a lot of information lost here. – maxywb Sep 05 '13 at 14:49
  • I know, and yet it's what the OP says they want. – Joni Sep 05 '13 at 14:50