确定Python中特定数字的精度和比例
我在Python中有一个包含浮点数的变量(例如,确定Python中特定数字的精度和比例,python,string,floating-point,scale,precision,Python,String,Floating Point,Scale,Precision,我在Python中有一个包含浮点数的变量(例如,num=24654.123),我想确定这个数字的精度和刻度值(在Oracle意义上),所以123.45678应该给我(8,5),12.76应该给我(4,2),等等 我最初考虑使用字符串表示法(通过str或repr),但对于大数来说,这些表示法是失败的(尽管我现在明白了,这里的问题是浮点表示法的局限性): 编辑: 下面是好的观点。我应该澄清一下。该数字已经是一个浮点数,正在通过cx_Oracle推送到数据库中。在Python中,除了执行INSERT和
num=24654.123
),我想确定这个数字的精度和刻度值(在Oracle意义上),所以123.45678应该给我(8,5),12.76应该给我(4,2),等等
我最初考虑使用字符串表示法(通过str
或repr
),但对于大数来说,这些表示法是失败的(尽管我现在明白了,这里的问题是浮点表示法的局限性):
编辑:
下面是好的观点。我应该澄清一下。该数字已经是一个浮点数,正在通过cx_Oracle推送到数据库中。在Python中,除了执行INSERT和处理Oracle错误之外,我正在尽力处理对于相应数据库类型来说太大的浮动(因为我希望一次处理字段中的数字,而不是记录)。我猜<>代码> map(LeN,RePR(num).Seal'('.'))是我最接近浮点的精度和规模的地方。 < P>我认为你应该考虑使用类型而不是<代码>浮点。“代码>浮点< /代码>类型将给出舍入错误,因为数字是用二进制表示的,但许多十进制数没有精确的二进制表示形式。
使用十进制类型将有帮助,如果您想要很大的精度,请考虑使用,GNU多精度库到Python的端口。
获取小数点左侧的位数很容易:int(log10(x))+1
小数点右边的位数比较复杂,因为浮点值固有的不精确性。我还需要几分钟的时间来解决这个问题
编辑:基于这个原则,下面是完整的代码
import math
def precision_and_scale(x):
max_digits = 14
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)
(0)请确认或拒绝:您被赋予了可使用的浮动,这是不可避免的,您无法将数据作为十进制数据获取,Oracle数据类型包括基于十进制的类型,并且这种基本不匹配是不可避免的。请解释任何完全或部分否认
(1) 您的“大数失败”评论具有误导性/不相关/错误——您说您的起点是一个浮点,但1234567890.0987654321不能表示为浮点,如repr()的结果所示
(2) 也许您可以使用新的repr(python2.7和3.1),它提供了repr(x)的最小可能精度,仍然满足float(repr(x))==x
例如,旧repr(1.1)产生“1.10000000000001”,新repr(1.1)产生“1.1”
关于“我想map(len,repr(num).split('.')是最接近浮点的精度和比例?”:您需要一种策略来处理(a)负数和零数(b)像1.1e20
如果需要使用Python2.6或更早版本,则在Objects/floatobject.c中挖掘应该为float对象的新repr()打开c代码
(3) 如果您告诉我们相关Oracle数据类型的规格,我们可能会帮助您设计检查,以选择哪种类型可以包含给定的浮点值。浮点变量不可能。例如,打字
>>> 10.2345
给出:
10.234500000000001
因此,要从中获得6,4,您必须找到一种方法来区分用户输入的10.2345
和10.23450000000001
,这是不可能使用浮动的。这与浮点数的存储方式有关。使用十进制
import decimal
a = decimal.Decimal('10.234539048538495')
>>> str(a)
'10.234539048538495'
>>> (len(str(a))-1, len(str(a).split('.')[1]))
(17,15)
似乎
str
是比repr
更好的选择:
>>> r=10.2345678
>>> r
10.234567800000001
>>> repr(r)
'10.234567800000001'
>>> str(r)
'10.2345678'
我找到了另一个似乎更简单的解决方案,但我不确定它是否适用于所有情况
import math
x = 1.2345678
def flip(string):
result = ""
for ch in string:
result = ch + result
return result
prec = int(math.log10(float(flip(str(x)))) + 1 # precision as int
如果需要检查精度,可以尝试:
def prec_check(a,b)
a = str(a)
b = str(b)
do = bool(True)
n = 0
while do == True:
if a and b and a[n] == a[b]:
n += 1
else:
do = false
return n
如果需要检查(a和b的)相应位数
请注意,这不适用于“十进制”模块。适用于浮点数;看看我的答案,我的答案也行。关键是将位数限制在已知的浮点类型精度范围内,并对结果进行四舍五入。0。基本上是肯定的。一切都设置为使用浮点,我不相信cx_Oracle会处理十进制类型,至少我已经设置好了。1.编辑以更正。2.有趣,不幸的是我落后于2.7。3.我正在尝试编写动态工作的代码,即使Oracle列类型在精度或规模上发生变化。(哎哟,抱歉格式不好)出于好奇,14号是从哪里来的?它是否独立于平台?它依赖于平台,但大多数平台将使用IEEE-754。我可能会把它改为15,但我想保守一点,确保我的舍入工作正常。如果没有14个硬编码,是否可以从Python发行版获得?@aaragon可能,我不知道。因为我知道的每一个Python版本都是基于IEEE-754的,所以我没有动力去寻找.Lambda函数,它用于查找小数点右边的位数
Lambda x:len(str(x).split('.')[-1]),如果len(str(x).split('.')>1,如果我们想为100.0输入Lambda x:len返回0(str(x).split('.)[-1]),如果int(x)1其他0
def prec_check(a,b)
a = str(a)
b = str(b)
do = bool(True)
n = 0
while do == True:
if a and b and a[n] == a[b]:
n += 1
else:
do = false
return n
def prec_check(a, b):
a = str(a)
b = str(b)
do = bool(True)
n = 0
while do == True:
if a and b and a[n] == a[b]:
n += 1
else:
do = false
return n