Parsing Large Numbers - python

I am writing some simple code to raise a base value to a power
then perform some operations on the output.
I have included the code I am using now, below ( see end of this message ), also see immediately below what this looks like when I run my script from the console :
.........................................
C:\PYTHON34>python tst.py
INPUT Value: 431.1
INPUT Power Value; 1.9907
RESULT 1739.554505641426658257842063903808593750000000000000000000000000
.........................................
This is the code I am currently using :
import time
e0=time.time()
c0=time.clock()
import sys
import math
from sympy import mpmath
from mpmath import *
mpmath.mp.dps = 10000
inputx = float(input('Enter inputx Value: '))
powerx =float(input('Enter Power Value; '))
inputx_squared = float((mpmath.power(inputx, powerx)))%1999
print('\r')
print('RESULT ', '%.60f' % inputx_squared)
elapsed_time=time.time() -e0
cpu_time=time.clock() -c0
print('\r')
print("CPU TIME ;", cpu_time)
What I need to be able to do ;
1.) Store whole number value to left of the decimal point without decimals to a variable = x
2.) Grab entire decimal value to the right of the decimal point and store in a variable = y
Parse (y) according to some simple rules. Here's where it gets trick for me.
What I want to do is examine (y) to see if there are any leading leading and trailing zeros
In the example ; "1739.554505....." IF this value was instead, something like any of the following ;
1739.0554505
1739.00554505
1739.000554505
Then I want to extract the whole number less any continuous leading zeroes
NEXT, I want to cut the number so that when there are four continuous trailing zeros, all zeros starting from the first one that started off the first four continuous zeros and all following zeroes are
truncated
So in our example ;
"1739.554505641426658257842063903808593750000000000000000000000000"
(y) becomes "55450564142665825784206390380859375"
Next I want to take the mod of above value by %1999
This returns "1407"
Next I want to join this value AS the decimal value to the right as ;
1739.1407

I agree with the first comment and would recommend using strings.
Result = 1739.554505641426658257842063903808593750000000000000000000000000
z = str(Result).split(".")
x = z[0]
y = z[1].strip("0")
mode = int(y)%1999
new_res = float(x+"."+str(mode))
print(new_res)
>>>1739.1407
The strip() method removes all leading and trailing zeros.
And I am also interested in the application of such operations.

Have you considered using the Decimal type:
import math
from decimal import Decimal, getcontext
getcontext().prec = 60
inputx = Decimal('431.1')
powerx = Decimal('1.9907')
inputx_squared = (inputx ** powerx) % 1999
x = math.floor(inputx_squared)
y = inputx_squared - x
which gives you
In: x
Out: 1739
In: y
Out: Decimal('0.554505641528269687606334953784096474037969748439285550')

Related

Python not returning all the zeros but e-n

I have a python code that when given a small number between 0 and 1 doesn't print it fully, but 4.43017984825e-7 for example,how do I make the code shows the whole number with all zeroes?
this was my try:
number="4.43017984825e-7"
result=number.find("e")
new=list(number)
last=int(new[-1])
print(last)
del new[13:16]
print(new)
pricee=(''.join(new))
print(pricee)
price=float(pricee)*10**-(last)
print(price)
Note: the number changes everytime, so I want it to be applicable for all numbers.
You can probably accomplish what you want with fixed-point formatting.
>>> x=4.43017984825e-7
>>> print(x)
4.43017984825e-07
>>> print(f"{x:20.18f}")
0.000000443017984825
The 20 in that format tells the full width you want, while the 18 tells the number of decimals.
Now, this is fairly specific to this number, you'll have to pick the right length and number of decimals for your actual application.
Expanding on the suggestion from #MostafaFarzán: you can use log10 to adjust that fixed point formatting to any number:
x = <some float>
significant_digits = 8
decimals=max(0, int(-log10(x) + significant_digits))
print(f"%.{decimals}f" % x)
or, more concisely but harder to read:
print(f"%.{max(0, int(-log10(x) + 8))}f" % x)

How can I check the length of a long float? Python is truncating the length [duplicate]

I have some number 0.0000002345E^-60. I want to print the floating point value as it is.
What is the way to do it?
print %f truncates it to 6 digits. Also %n.nf gives fixed numbers. What is the way to print without truncation.
Like this?
>>> print('{:.100f}'.format(0.0000002345E-60))
0.0000000000000000000000000000000000000000000000000000000000000000002344999999999999860343602938602754
As you might notice from the output, it’s not really that clear how you want to do it. Due to the float representation you lose precision and can’t really represent the number precisely. As such it’s not really clear where you want the number to stop displaying.
Also note that the exponential representation is often used to more explicitly show the number of significant digits the number has.
You could also use decimal to not lose the precision due to binary float truncation:
>>> from decimal import Decimal
>>> d = Decimal('0.0000002345E-60')
>>> p = abs(d.as_tuple().exponent)
>>> print(('{:.%df}' % p).format(d))
0.0000000000000000000000000000000000000000000000000000000000000000002345
You can use decimal.Decimal:
>>> from decimal import Decimal
>>> str(Decimal(0.0000002345e-60))
'2.344999999999999860343602938602754401109865640550232148836753621775217856801120686600683401464097113374472942165409862789978024748827516129306833728589548440037314681709534891496105046826414763927459716796875E-67'
This is the actual value of float created by literal 0.0000002345e-60. Its value is a number representable as python float which is closest to actual 0.0000002345 * 10**-60.
float should be generally used for approximate calculations. If you want accurate results you should use something else, like mentioned Decimal.
If I understand, you want to print a float?
The problem is, you cannot print a float.
You can only print a string representation of a float. So, in short, you cannot print a float, that is your answer.
If you accept that you need to print a string representation of a float, and your question is how specify your preferred format for the string representations of your floats, then judging by the comments you have been very unclear in your question.
If you would like to print the string representations of your floats in exponent notation, then the format specification language allows this:
{:g} or {:G}, depending whether or not you want the E in the output to be capitalized). This gets around the default precision for e and E types, which leads to unwanted trailing 0s in the part before the exponent symbol.
Assuming your value is my_float, "{:G}".format(my_float) would print the output the way that the Python interpreter prints it. You could probably just print the number without any formatting and get the same exact result.
If your goal is to print the string representation of the float with its current precision, in non-exponentiated form, User poke describes a good way to do this by casting the float to a Decimal object.
If, for some reason, you do not want to do this, you can do something like is mentioned in this answer. However, you should set 'max_digits' to sys.float_info.max_10_exp, instead of 14 used in the answer. This requires you to import sys at some point prior in the code.
A full example of this would be:
import math
import sys
def precision_and_scale(x):
max_digits = sys.float_info.max_10_exp
int_part = int(abs(x))
magnitude = 1 if int_part == 0 else int(math.log10(int_part)) + 1
if magnitude >= max_digits:
return (magnitude, 0)
frac_part = abs(x) - int_part
multiplier = 10 ** (max_digits - magnitude)
frac_digits = multiplier + int(multiplier * frac_part + 0.5)
while frac_digits % 10 == 0:
frac_digits /= 10
scale = int(math.log10(frac_digits))
return (magnitude + scale, scale)
f = 0.0000002345E^-60
p, s = precision_and_scale(f)
print "{:.{p}f}".format(f, p=p)
But I think the method involving casting to Decimal is probably better, overall.

Work out significant decimal points to format floating point number

I found this which covers how to suppress scientific notation, but I'd like to go a step further and also work out the formatting string (i.e. the number of required decimal points to represent a number).
My idea so far is to assume a very high resolution (20 in this example) and reduce trailing zeroes as suggested in the accepted answer here. Is there perhaps a better way to achieve this?
>>> f = 0.00000008
>>> s = '{:.20f}'.format(f)
>>> s
'0.00000008000000000000'
>>> s.rstrip('0')
'0.00000008'
Note, I don't want scientific notation either (which you would get with a formatting string of {:g}).
The max number of significant digits in a float is 15 (the power is separate from this). So there's no point in accounting for more digits past that, as they wouldn't be right. Knowing what the power of ten for a given number will tell you how many zeros to pad out in the front.
If what you're formatting will never get above one, then the following will suffice:
from math import log10
def floatformat(f):
pwr = log10(f)
return '{:.0{}f}'.format(f, int(abs(pwr)) + 15).rstrip('0')
But if you're parsing any possible float value, you'll have to handle large numbers a bit differently to get trailing zeros and not random inaccurate digits.
def floatformat(f):
sigs = 15 # number of accurate digits that a float can contain
pwr = log10(f)
if pwr > sigs: # power above accurate digits
s = '{:.{}f}'.format(f / 10 ** int(pwr), sigs)
s = s.replace('.', '') # remove decimal point, no longer necessary here
s = s + '0' * (int(pwr) - sigs) # add in trailing zeros
elif 0 < pwr <= sigs: # power within accurate digits
s = '{:.{}f}'.format(f, sigs - int(pwr)).rstrip('0')
else: # power below accurate digits
s = '{:.0{}f}'.format(f, int(abs(pwr)) + sigs).rstrip('0')
if s[-1] == '.': s = s[:-1] # remove trailing decimal point if needed
return s
All this is doing is keeping the accurate digits, then shuffling them around to have the correct power without the scientific notation.
Examples:
>>> floatformat(0.00000008)
'0.00000008'
>>> floatformat(0.0000000000000000000000000000008)
'0.0000000000000000000000000000008'
>>> floatformat(0.00000000000000000000000000000080067)
'0.00000000000000000000000000000080067'
>>> floatformat(2.31451103e7)
'23145110.3'
>>> floatformat(2.31451103e3)
'2314.51103'
>>> 935.16087e203 == float(floatformat(935.16087e203)) # conversion check to see if power is handled correctly
True
>>> import sys
>>> floatformat(sys.float_info.max)
'179769313486231600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
>>> floatformat(sys.float_info.min)
'0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072'

universal method for working with currency with no rounding, two decimal places, and thousands separators

i am a newbie learning python (2.7.3) and was given a simple exercise calculating costs but soon became interested in really being able to control or understand the 'exactness' of the results that were being produced. if i use the calculator on my computer i get the results i think i am after (ie they seem very specific), but if i use python it seems i have to be very exact about how i add formatting information to the values being used and printed.
the short version of my question is:
is there an easy solution that i can use whenever i am working with currency that returns:
two decimal places to the right of the decimal point
does no rounding up (ie basically just 'truncates' whatever is to the right of the second place after the decimal point)
adds thousand separators if necessary
i've been mucking around with the interpreter (see code below) testing variations if anyone wants to run it to see the results and variations.
thank you.
# basic entry - both are seen as integers
print 'A: ', 7/3
# test by printing out the types
print 'B: ', type(7)
print 'C: ', type(3)
# this is not necessary as they are already integers
print 'D: ', int(7/3)
# converts the result of 7/3 into a floating number
print 'E: ', float(7/3)
# defines the float version of 7 by the float version of 3
print 'F: ', float(7) / float(3)
# coverts the results of the above into a string and assigns to variable
string_var = str(float(7) / float(3))
# print the string
print 'G: ', string_var
# prints 4 characters of the string, but returns two decimal places
print 'H: ', string_var[:4]
string_var = str(25.8545678888)
# prints 5 characters of the string, but returns two decimal places
print 'I: ',string_var[:5]
# import the locale module
import locale
# sets to user's default settings (don't know what empty quotes are)
locale.setlocale( locale.LC_ALL, '' )
#set an arbitrary float number to a variable
float_var = 25.859
# apply locale.currency formatting
print 'J: ',locale.currency(float_var)
# import the decimal module
from decimal import *
# the decimal version of the variable
print 'K: ',Decimal(float_var)
# divide the decimal version by 2
print 'L: ',Decimal(float_var) / 2
# divide the decimal version by the decimal verson of 2
print 'M: ', Decimal(float_var) / Decimal(2)
# change decimal precision to 6
getcontext().prec = 6
# note there is no change in this value as precision only applied to
# result of calculations, see
#http://stackoverflow.com/questions/6483440/python-decimal-precision
print 'N: ', Decimal(float_var)
# the following equation returns decimal precision to 6 (6 characters displayed)
print 'O: ', Decimal(float_var) / 2
# example of 6 characters printed, not decimal places
# to the right of the decimal
print 'P: ', Decimal(55550) / 130
# if you want to control places to the right of the decimal
# displayed without rounding and show thousand separators if
# necessary ?
EDIT:
thanks all for replies, this is the solution i went with which is sort of a mix of all replies:
def make_it_money(number):
"""
always:
- shows 2 decimal places
- shows thousands separator if necessary
- retains integrity of original var for later re-use
- allows for concise calling
"""
import math
return '$' + str(format(math.floor(number * 100) / 100, ',.2f'))
# tests
var1 = 25.867
var2 = 25.864
var3 = 25.865
var4 = 2500.7869
print make_it_money(var1)
print make_it_money(var2)
print make_it_money(var3)
print make_it_money(var4)
Use the format() function to format float or Decimal types:
format(value, ',.2f')
which results in:
>>> format(12345.678, ',.2f')
'12,345.68'
The , adds a comma as a thousands separator in the output.
You generally do not want to indiscriminately round down after floating point or Decimal calculations. If you feel you have to do that anyway, do so explicitly before formatting:
>>> import math
>>> format(math.floor(12345.678 * 100) / 100, ',.2f')
'12,345.67'
Python inherits a lot from C and as such you can use the print %.2f syntax to print a float with only 2 values after the comma, this will round the value however it seems.
A thousands separator seems easy as well, have a look at this question/answer on SO:
https://stackoverflow.com/a/5513747/1093485
You could also import an existing module such as python-money (https://pypi.python.org/pypi/python-money)

How to identify the tenths part of a float in Python?

After looking at the various math, float, and decimal functions in Python, I haven't found what I'm looking for. In my program, there may be instances when it will return a float and I need the float information so that I can do another function. Let's say based on the user's input the quotient we're working with is 1.4, which I will represent as X.Y. How do I isolate Y so that I can use a FOR statement. (I need the program to do something 4 times in this case.) I've tried playing with the % function, but that returns the remainder, not the value I'm looking for. I've tried math.fmod and math.modf. Again not what I'm looking for. I looked at this example too.
Looks like int((x*10) % 10) will do it:
>>> x = 1.4
>>> int((x*10) % 10)
4
How about
x = 1.4
y = 10 * (x - int(x))
>>> 4
or you could do it as string manipulation
x=1.4
whole,fractional = map(int,str(x).split("."))
afterwards whole is equal to 1 and fractional is equal to 4... and it should work equally well with negative numbers
Using the following method you can get any position in a float. That is, tenths, hundredths, thousandths and so on:
import math
def get_pos_float(num, unit):
if unit >= 10:
num = abs(math.modf(num)[0]) # Get just the fractional part
num *= 10 # Move the decimal point one place to the right
return get_pos_float(num, unit/10)
return int(math.modf(num)[1]) #Return the whole number part
decimalNumber = 13.24
print(get_pos_float(decimalNumber, 10)) # prints the tenths decimal position 2
print(get_pos_float(decimalNumber, 100)) # prints the hundredths decimal position 4
print(get_pos_float(decimalNumber, 1000)) # prints the thousandths decimal position 0

Categories

Resources