9

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

我首先考虑使用字符串表示(通过stror repr),但是对于大数字来说这些都失败了(尽管我现在明白这是浮点表示的局限性,这就是这里的问题):

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

编辑:

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

4

11 回答 11

20

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

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)
于 2010-06-10T22:32:45.910 回答
6

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

>>> 10.2345

给出:

10.234500000000001

因此,要从中获得 6,4,您将必须找到一种方法来区分用户输入10.2345and 10.234500000000001,而这是使用浮点数不可能实现的。这与存储浮点数的方式有关。使用decimal.

import decimal
a = decimal.Decimal('10.234539048538495')
>>> str(a)
'10.234539048538495'
>>>  (len(str(a))-1, len(str(a).split('.')[1]))
(17,15)
于 2010-06-10T23:09:08.110 回答
4

似乎strrepr

>>> r=10.2345678
>>> r
10.234567800000001
>>> repr(r)
'10.234567800000001'
>>> str(r)
'10.2345678'
于 2010-06-11T04:11:54.833 回答
3

我认为您应该考虑使用小数类型而不是float. 该float类型会产生舍入错误,因为数字在内部以二进制表示,但许多十进制数字没有精确的二进制表示。

于 2010-06-10T21:43:13.360 回答
2

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

(1)您的“大数失败”言论具有误导性/不相关/错误——您说您的起点是浮点数,但 1234567890.0987654321 不能表示为浮点数,如 repr() 的结果所示。

(2) 也许您可以使用新的 repr(Python 2.7 和 3.1),它提供了仍然满足 repr(x) 的最小可能精度float(repr(x)) == x

例如,旧的 repr(1.1) 产生“1.1000000000000001”,新的 repr(1.1) 产生“1.1”

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

如果您需要使用 Python 2.6 或更早版本,则在 Objects/floatobject.c 中挖掘应该会显示浮点对象的新 repr() 的 C 代码。

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

于 2010-06-10T23:08:00.703 回答
1

基本上,您不能使用浮点数。 使用小数类型会有所帮助,如果您想要非常高的精度,请考虑使用gmpyGNU 多精度库到 Python 的端口。

于 2010-06-10T21:44:23.827 回答
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
于 2019-06-18T13:13:58.860 回答
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
于 2020-06-03T15:38:42.730 回答
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

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

于 2020-06-03T15:45:33.293 回答
0

逗号后的多个符号。适用于int,floatDecimal类型。

def get_num_precision(num):
    count = 0
    while num * 10**count % 1 != 0:
        count += 1
    return count
于 2021-11-25T14:35:11.383 回答
0
def get_precision(f1):
    str1=str(f1)
    return len(str1.split(".")[1])
于 2022-02-25T06:32:17.460 回答