确定Python中特定数字的精度和比例

时间:2010-06-10 21:40:51

标签: python string floating-point scale precision

我在Python中有一个包含浮点数的变量(例如num = 24654.123),我想确定数字的精度和比例值(在Oracle意义上),所以123.45678应该给我(8 ,5),12.76应该给我(4,2)等。

我第一次考虑使用字符串表示(通过strrepr),但那些大数字失败(虽然我现在明白浮点表示的局限性是这里的问题) :

>>> num = 1234567890.0987654321
>>> str(num) = 1234567890.1
>>> repr(num) = 1234567890.0987654

修改

下面的好点。我应该澄清一下。该数字已经是一个浮点数,并通过cx_Oracle被推送到数据库。我正在努力尽我所能在Python中处理对于相应数据库类型来说太大而不执行INSERT和处理Oracle错误的浮点数(因为我想处理数字一个字段,而不是记录,在一段时间)。我猜map(len, repr(num).split('.'))是最接近浮点数的精度和比例的吗?

9 个答案:

答案 0 :(得分:14)

获取小数点左侧的位数很容易:

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)

答案 1 :(得分:4)

浮点变量不可能。例如,输入

>>> 10.2345

给出:

10.234500000000001

因此,要获得6,4,您必须找到一种方法来区分输入10.234510.234500000000001的用户,这是不可能使用浮点数。这与存储浮点数的方式有关。使用decimal

import decimal
a = decimal.Decimal('10.234539048538495')
>>> str(a)
'10.234539048538495'
>>>  (len(str(a))-1, len(str(a).split('.')[1]))
(17,15)

答案 2 :(得分:3)

我认为您应该考虑使用decimal类型而不是floatfloat类型将给出舍入错误,因为数字在内部以二进制表示,但许多十进制数字没有精确的二进制表示。

答案 3 :(得分:3)

似乎str是比repr更好的选择:

>>> r=10.2345678
>>> r
10.234567800000001
>>> repr(r)
'10.234567800000001'
>>> str(r)
'10.2345678'

答案 4 :(得分:2)

(0)请确认或否认:您将获得使用浮点数,这是不可避免的,您无法将数据作为十进制数据,Oracle数据类型包括基于十进制的类型,并且这种基本不匹配是不可避免的。请解释任何完全或部分拒绝。

(1)你的“大数字失败”评论是误导/无关/错误 - 你说你的起点是浮点数,但是1234567890.0987654321不能表示为浮点数,如repr的结果所示()。

(2)也许你可以使用NEW repr(Python 2.7和3.1),它提供仍然满足float(repr(x)) == x

的repr(x)的最小可能精度

E.g。 old repr(1.1)生成“1.1000000000000001”,new repr(1.1)生成“1.1”

关于“我猜map(len,repr(num).split('。'))是我最接近浮点数的精度和比例?”:你需要一个策略来处理(a)负数和零数(b)数字如1.1e20

如果你需要使用Python 2.6或更早版本,挖掘Objects / floatobject.c应该为浮动对象的新repr()打开C代码。

(3)也许如果您告诉我们相关Oracle数据类型的规范,我们可以帮助您设计检查以选择哪个类型可以包含给定的浮点值。

答案 5 :(得分:1)

Basically, you can't with floating point numbers.使用十进制类型会有所帮助,如果你想要非常大的精度,可以考虑使用gmpy,GNU Multiple Precision库的Python端口。

答案 6 :(得分:0)

我发现了另一个似乎更简单的解决方案,但是我不确定它是否适用于所有情况。

   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

答案 7 :(得分: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

答案 8 :(得分:0)

如果您需要检查(a和b)的对应位数

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

请注意,这不适用于“十进制”模块。