Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python等价于C strod 我正在把C++程序的部分转换成Python,但是我在替换C函数时遇到了一些困难。 我正在研究的字符串由简单的数学ish方程组成,例如“KM/1000.0”。问题是常量和数字都是混合的,因此我无法使用float()_Python_Strtod - Fatal编程技术网

Python等价于C strod 我正在把C++程序的部分转换成Python,但是我在替换C函数时遇到了一些困难。 我正在研究的字符串由简单的数学ish方程组成,例如“KM/1000.0”。问题是常量和数字都是混合的,因此我无法使用float()

Python等价于C strod 我正在把C++程序的部分转换成Python,但是我在替换C函数时遇到了一些困难。 我正在研究的字符串由简单的数学ish方程组成,例如“KM/1000.0”。问题是常量和数字都是混合的,因此我无法使用float(),python,strtod,Python,Strtod,如何编写Python函数来模拟返回转换后的数字和下一个字符的位置的strod 我不知道有任何现有的函数可以做到这一点 但是,使用正则表达式编写一个非常简单: import re # returns (float,endpos) def strtod(s, pos): m = re.match(r'[+-]?\d*[.]?\d*(?:[eE][+-]?\d+)?', s[pos:]) if m.group(0) == '': raise ValueError('bad float: %s

如何编写Python函数来模拟返回转换后的数字和下一个字符的位置的strod

我不知道有任何现有的函数可以做到这一点

但是,使用正则表达式编写一个非常简单:

import re

# returns (float,endpos)
def strtod(s, pos):
  m = re.match(r'[+-]?\d*[.]?\d*(?:[eE][+-]?\d+)?', s[pos:])
  if m.group(0) == '': raise ValueError('bad float: %s' % s[pos:])
  return float(m.group(0)), pos + m.end()

print strtod('(a+2.0)/1e-1', 3)
print strtod('(a+2.0)/1e-1', 8)

一种更好的总体方法可能是先构建一个标记化表达式的表达式,然后使用一系列标记,而不是直接使用字符串(或者完全使用yacc样式的解析器)。

我将使用正则表达式:

import re
mystring = "1.3 times 456.789 equals 593.8257 (or 5.93E2)"
def findfloats(s):
    regex = re.compile(r"[+-]?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b", re.I)
    for match in regex.finditer(mystring):
        yield (match.group(), match.start(), match.end())
这将查找字符串中的所有浮点数,并返回它们及其位置

>>> for item in findfloats(mystring):
...     print(item)
...
('1.3', 0, 3)
('456.789', 10, 17)
('593.8257', 25, 33)
('5.93E2', 38, 44)

自己解析数字

递归下降解析器对于这种输入非常容易。 首先写一篇语法:

float ::= ipart ('.' fpart)* ('e' exp)*
ipart ::= digit+
fpart ::= digit+
exp   ::= ('+'|'-') digit+
digit = ['0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9']

现在,将此语法转换为函数应该很简单…

您可以创建一个简单的C
strod
包装器:

#include <stdlib.h>

double strtod_wrap(const char *nptr, char **endptr)
{
   return strtod(nptr, endptr);
}
(如果您使用的是64位Python,那么编译器也必须是64位的)

并使用python中的
ctypes
调用它(linux:将
.dll
更改为
。因此在lib目标和下面的代码中,这是在Windows上测试的):

印刷品:

(12.5, b'hello')
(这并不像看上去那么难,因为我10分钟前就学会了)

关于
ctypes


你不能事先拆分字符串吗?你也需要解析指数符号吗?这是Python源代码中的c代码,如果你想重新实现的话——我可以想到一堆不会被提取的有效浮点。正则表达式假定为整数部分。其他一切都是可选的。如果有小数点,则需要小数部分。因此,
.1
1.
将不会被拾取。当然,如果需要的话,修改正则表达式是很简单的;您应该能够直接使用strod来实现这一点。这样会更好。我必须首先测试:)您应该能够从特定于平台的现有共享库文件加载
strod
ctypes.cdll.msvcrt
应该可以在Windows上运行。我相信它在Linux上通常是
cdtypes.CDLL('libc.so.6')
,但我不知道这有多普遍。您也可以编译自己的文件,从中访问
strod
,尽管我不确定详细信息是什么。(
#include
本身似乎可以工作。)我在C文件中单独尝试了单个stdlib.h include,但似乎
strtod
符号没有链接,因此无法工作(python找不到它)。现在还是用空包装纸吧。它正在工作,并且它在源代码级别可以移植到.dll/.so部分之外。如回答中所述,我不是ctypes专家。刚刚让它工作了(python代码的简单性给我留下了深刻的印象)。在
float
@的定义中,在
ipart
之前应该有一个
(“+”|“-”)
,这取决于上下文。当解析单个独立数字时,确实需要解析前导符号。解析数字表达式时,避免包含符号,因为它会允许出现“42-+37.2”这样的奇怪表达式(我似乎记得我是从一种著名语言的语法中复制了这种语法)
42-+37.2
对我来说似乎是一个合理的表达式。尽管它对任何有数学倾向的人来说都是合理的,这种语法意味着你也可以编写<代码> 42——37.2代码>,这混淆了C或C++分析器(但是奇怪的C++接受了代码> 42 + 37.2 < /代码>)。因此,许多(大多数)编程语言将前导符号视为一元运算符,也就是说,一个与下面的数字明显分开的实体。有些语言不允许一元运算符位于表达式开头以外的任何位置。无论如何,对于独立数字的简单解析,上面的语法确实缺少这些一元运算符。
import ctypes

_strtod = ctypes.CDLL('libstrtod.dll')
_strtod.strtod_wrap.argtypes = (ctypes.c_char_p, ctypes.POINTER(ctypes.c_char_p))
_strtod.strtod_wrap.restype = ctypes.c_double

def strtod(s):
    p = ctypes.c_char_p(0)
    s = ctypes.create_string_buffer(s.encode('utf-8'))
    result = _strtod.strtod_wrap(s, ctypes.byref(p))
    return result,ctypes.string_at(p)

print(strtod("12.5hello"))
(12.5, b'hello')