如何测试数字是不是存在科学记数法? [关闭]

Posted

技术标签:

【中文标题】如何测试数字是不是存在科学记数法? [关闭]【英文标题】:How to test a number for presence of scientific notation? [closed]如何测试数字是否存在科学记数法? [关闭] 【发布时间】:2011-09-21 06:34:17 【问题描述】:

如何测试存储为字符串的数字是否为指数数字(在 Linux 中)?

我可以使用扫描数字和查找是否存在“e”等方法,但我需要一种更智能的方法来查找。

是否有任何 API 可以快速找出并判断它是否为指数?

我可以使用蛮力方法,例如搜索整个字符串,然后得到一个“e”,后跟一个 +/-,然后是一个数字。但我需要一种更快、更智能的方法,消耗更少的机器周期。

P.S:指数数字是这样的数字:43e4、23e-2(任何数字之间有e

【问题讨论】:

...什么是指数? 没错,但我确信任何实现这一点的 API 都会做类似的事情。 你可以这样想:除非遍历整个数字,否则无法验证没有e 一个字符串是一个字符串,要测试它是否有单个字符只能通过一种方式完成,从一个索引开始搜索它并在另一个索引处结束搜索。如果找到了,做点什么,如果没有,做点别的。当你说它需要更多的“处理器周期”时,你在比较什么?如果您知道在字符串中查找字符的更好方法,请告诉我们! @kingsmasher1,它更慢,因为正则表达式 更慢...并且在这个特定问题中具有与字符串搜索相同的可用性。 【参考方案1】:

指数不存在。存储在floatdouble 中的数字对于输入0.011E-2 具有相同的位模式。数字也不存储在字符串中。字符串存储在字符串中。因此,如果您将数字转换为字符串,您可以隐式或显式选择某种转换。转换后,您只处理数字的表示,而不是数字本身。

如果您的转换选择将数字 0.1 转换为字符串 "1E-1""0.1""10^-1" 它会 - 使用您的定义 - 仅在三种情况之一中的指数数?这只有在非常有趣的场景中才有意义,所以请退后一步想想,真正的问题是什么。

【讨论】:

我有数字说我正在将数字转换为字符串,但它是另一种方式。如果我知道它是一个数字并且它有一个 E,那么故事就到此结束。 然后只是解析它,有两种方法:解析它(正如我回答的那样)或正则表达式它。或者,如果您愿意,将其转换为double,然后检查结果...【参考方案2】:
regex_t re;
regcomp(&re, "^([0-9]+[.]?[0-9]*|[0-9]*[.][0-9]+)[eE][+-]?[0-9]+$", REG_EXTENDED);
if (!regexec(&re, str, 0, 0, 0)) /* It's an "exponential number" */

【讨论】:

我对 shell 脚本不感兴趣 :-)(将正则表达式转换为十六进制会更容易),我们可以在 C 中实现正则表达式吗? 那是 C。假设您有 POSIX 或兼容 POSIX 的正则表达式库可供您使用。 正如 Griewes 所说,你认为这是一个缓慢的过程吗? (消耗更多的机器周期)并且与蛮力方法一样好? 如果你编译一次正则表达式(regcomp)然后测试保持regex_t并用于多个regexec测试,它应该非常快,但它肯定会使用更多的内存比只调用strchrstrtod 的天真方法。如果您打算稍后将字符串转换为数字,只需调用 strtod 和更好的方法。 :再次感谢您的精彩解释。【参考方案3】:

我假设给定一个已知可解析为数字的字符串,您想知道它是否采用科学计数法,即其中有一个 e

使用标准库的strchr 函数是否足够聪明?

char *num_str = "43e4";

if (strchr(num_str, 'e'))

    /* It's in scientific notation! */
    ...

更多strchr 文档: http://www.gnu.org/software/libc/manual/html_node/Search-Functions.html#index-strchr-549

【讨论】:

如果有,43ee2 怎么办? API 还应该告诉它是否是一个有效的数字和范围。就像strtolstrtod 一样 e 也是一个有效的十六进制数字:0xdeadbeef @Keith Thompson:我喜欢指数数字,而不是十六进制数。 @kingsmasher1:请不要再称它们为“指数数”,这不是它们的名称。您正在测试代表数字的某些 字符串 @Keith Thompson:我对任何代表数字的字符串都不感兴趣,我对代表指数数字的字符串感兴趣。它们是科学符号E 指数,否则它们叫什么?请告诉我们。【参考方案4】:

看看 lex(或 flex)。

我用于识别科学记数法数字的 lex 规则如下:

DIGIT*\.DIGIT+[eE][+-]?DIGIT+  |
DIGIT+\.DIGIT*[eE][+-]?DIGIT+  |
DIGIT+[eE][+-]?DIGIT+

其中 DIGIT 定义为:

DIGIT       [0-9]

【讨论】:

把它放在一个单一的 C 代码中怎么样? @kingsmasher1:试试自己怎么样?【参考方案5】:

我看不出用 strchr( number, 'e' ) 或 strchr( number, 'E' ) 检查你是否有科学记数法会有什么问题。为了防止 kingsmasher1 解释的问题,您应该检查 sscanf 是否会接受该字符串作为有效字符串。

另一种方法(未测试)可能是使用“%f”和“%g”(“%e”)比较 sscanf 的结果。 请注意,e 可以显示为小写或大写字母。

【讨论】:

查看我对 Edmund 的评论。它也会解析无效数字。 @kingsmasher - 谢谢修复。 堆垛机您好,请详细说明Another approach (not tested) could be comparing the results of sscanf using "%f" and "%g" ("%e"). Note that the e could appear as lower or uppercase letter scanf%f%g 上的行为相同。两者都扫描任何浮点数。【参考方案6】:

第 1 步:要检查字符串是否可以解释为双精度,只需使用 strtod 并在之后检查 endptr

double strtod(const char *nptr, char **endptr);

第 2 步: 我怀疑是否存在用于检查表示为字符串的浮点数是否包含显式指数的 API。但是,这是一项微不足道的任务,我认为您应该简单地编写自己的函数。

int has_exp(const char* s) 
  while (*s != 0) 
    if (*s == 'e' || *s == 'E') return 1;
    s++;
  
  return 0;

【讨论】:

您的代码因双 e 而失败。无论如何,可以通过首先使用 strtod 解析,如果解析成功,则确定它是否是指数的。 对于 567EQW 也失败了。对吗? 是的,这样更好,为你点赞:) 但是上面的代码对于十六进制数字再次失败,因为它可以有一个E,抱歉没有upvote :-(

以上是关于如何测试数字是不是存在科学记数法? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

我如何知道字符串是不是是科学计数法中的数字?

如何在 R 中的 read.csv(或其他读取函数)中“关闭”科学记数法?

s3db文件用SQLite导出excel文件后长数字变成了科学计数?

CSV 导出的是科学计数 如何转换

Excel里数字太长显示为科学计数法如何显示完整数字

程序员如何科学地记日志