高效的科学计数法


12

前几天,我的化学老师向我们解释了科学记数法(使用小数并乘以十的幂可以更轻松地表达大数),这使我回到了几年前。在学习了基础知识之后,我们做了很多典型的数学问题,其中一些问题如下:

用科学计数法表示以下内容:
a)50000000
b)120000000000000
c)90000000000000000000000000000000000000
d)pi ^ e ^ i ^ j ^ k ^ std :: vector
...
z)200
...

我想:“什么?我们被告知,科学记数法被用来提高书写效率,但是某些情况下根本没有效率!”

考虑数字

300

及其科学表示法:

3x10^2

什么,科学标记的版本实际上会占用更多空间?现在我们不能拥有它了吗?(屏幕空间是宝贵的。)
我们可以确定自己是否可以用科学计数法写数字更节省空间,或者...

任务

您的程序或函数应输入n任意大小的正数(取决于语言所支持的大小),并输出科学编号的数字。
但是,如果n在删除尾随零和尾随小数位后,原始数字显示的字符数少于或等于其科学标记版本的字符数,则必须输出该原始数字n

您的代码必须尽可能短,因为输出也必须尽可能短。

技术指标

高效科学计数法定义如下:

bx10^e

b是输入数除以10的幂以得出的值1 <= b < 10。该数字必须删除所有结尾的零(如果需要,还包括小数点),但必须具有原始数字的精度(当然,要达到您语言中的小数点限制)。也就是说,90000变成913.500变成1.350.000675变成6.75等。如果该数字最终包含的小数位数超出了您的语言所能处理的范围,则应四舍五入到最大小数位数。

e是将十提高到的指数n = b x 10^e(请记住,如果n小于1 ,则此数字必须为负)。此数字不应有任何尾随零或小数点(主要是因为如果它不是整数,那是错误的...)。

字符x10^ 必须保留在b和之间的字符串中e

测试用例

Input -> output
1 -> 1
20 -> 20
3000000 -> 3x10^6
400000 -> 400000
0.008093 -> 0.008093
0.007835000000000 -> 0.007835
0.000003000000 -> 3x10^-6
0.00000065 -> 6.5x10^-7
0 -> 0

计分

这是,因此以字节为单位的最短代码获胜。

其他规则和说明

  • 尾随零(和/或尾随小数位)不计入原始输入数字的字符数n。对于测试用例6这样的情况,请记住这一点
  • 您可以假设,如果输入数字小于1,则对于位数字总是以0开头(如测试用例5-8)。
  • 输入数字永远不会为负
  • 不允许使挑战变得微不足道的内置插件和标准漏洞
  • 输出中的尾随换行符可以

编辑
感谢user81655指出测试用例7和8具有错误的10的幂。现在,我已修复了这些问题,因此请确保您的代码正确评估了它们。


7
所以,呃,我应该问输入的输出pi^e^i^j^k^std::vector是什么吗?
Geobits '16

@Geobits Hmm,好吧,如果您可以为std :: vector分配一个数值,那么也许……不,输入中将只存在数字(浮点输入的小数点除外)。
MCΔT16年

这将容易得多,并且如果使用它我们将占用更少的“宝贵屏幕空间” e:(9000 -> 9e3几乎超过9,000个!)
Cyoce

1
@Cyoce我曾考虑过这一点,但我确实将这一挑战基于它的一般编写方式(如物理编写方式),似乎与在一起x10^。在这个问题上,这将是相当多的返工,因为它已经发布,我认为这不合适吗
MCΔT16年

1
@ghosts_in_the_code她没有,所以“把我带回了几年,当我第一次知道它[在数学课]”
MCΔT

Answers:


4

ES6,83 81个字节

x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y

对于某些toString坚持指数格式的极端情况,可能会失败。

编辑:由于@ user81655,节省了2个字节。


好主意。顺便说一句,您好像忘记/了正则表达式的结尾。
user81655 '02

您也可以稍微重新排列以节省2个字节:x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y
user81655 '16

@ user81655啊,发生的事情是我的浏览器以我认为新行误入新行的方式包裹了长行,使我感到困惑。
尼尔

2

Python 3中,346个 342 319 302字节

L=len;N=str(float(input()))
if N.endswith('.0'):N=N[:-2]
if'e'in N:C,P=N.split('e');N=N.replace('e','x10^')
else:
 C=N.strip('.0').replace('.','');F=N.find('.')
 if L(C)>1:C=C[0]+'.'+C[1:]
 P=((L(N) if F==-1 else F)-1-N.lstrip('0').find(C[0]))
print(min([N,'{0}x10^{1}'.format(C,int(P))],key=L))

大概太棒了,但是,这是我第一次尝试这样的运动。很难读,所以一定很好。

据我所知,即使Python倾向于将超出任何阈值的数字自动转换为科学计数法(除非带有那种酷炫的“ e”),它也应适用于所有情况。我不记得我是如何使它能够返回标准表格号的,但是它确实做到了。


2

Perl 6,96 90字节

我觉得这可能会更短,但这是我目前最好的

{my \s=($_,*×(1>$_??10!!.1)…10>*>=1);min(s[*-1]~"x10^"~(1>$_??1-s!!s-1),$_,by=>&chars)}

用法:将其分配给变量

在这里,它带有一些不好的注释,这是不满意的:

my &f = -> $n {
    my $a = 1 > $n ?? 10 !! .1;             # If $n < 1, we will multiply by 10
                                            # in the sequence below, else by 0.1

    my @seq = ($n, * × $a ... 10 > * >= 1); # Sequence starting at $n, 
                                            # multiply the previous value by $a
                                            # until we reach a number 1 <= x < 10

    # Join the last element in @seq, "x10^", and the length of @seq,
    # with an extra subtraction for numbers less than 1.
    # this gets us our scientific notation.
    my $science = @seq[*-1] ~ "x10^" ~ @seq - (1 > $n ?? @seq*2 !! 1); 

    min($science, $n, by => &chars) # Uses the &chars function to
                                    # choose a min value and return it.
}

$_ <11>$_以及1 <=* <1010>*>=1
布拉德·吉尔伯特b2gills '16

我本来打算昨晚这样做的,但我忘了。到家时,我会对其进行更新
热键

2

TI BASIC(nspire):112字节

Define f(x)=
Prgm
string(x)➝a
If x≥1 Then
format(x,"s")➝a
EndIf
instring(a,"ᴇ")➝b
left(a,b-1)&"x10^"&mid(a,b+1)➝a
If dim(a)<dim(string(n)) or x<1 Then
Disp a
Else
Disp x
Endif
EndPrgm

说明

If x≥1 Then
format(x,"s")➝a
EndIf

如果输入的格式不是科学格式,则使用格式功能将其转换为科学计数法-小数位会自动转换。

instring(a,"ᴇ")➝b
left(a,b-1)&"x10^"&mid(a,b+1)➝a

查找表示指数的花式E的位置,并将其替换为“ x10 ^”。

If dim(a)<dim(string(x)) or x<1 Then
Disp a
Else
Disp x
Endif

检查哪个输出更大并返回最佳输出。除非它是一个小十进制数,否则默认情况下较小。


0

Python(3.5)177字节

使用正则表达式的解决方案

import re
g=lambda s:re.sub(r"e\+?(-?)0?","x10^\\1",s)
def f(i):
 t=g(re.sub(r"\.[0]*e","e","%e"%i))
 u=g(re.sub(r"(\..*)[0]*$","\\1",str(i)))
 return t if len(u)>len(t) else u

说明

导入正则表达式模块

import re

lambda函数的定义e由替换x10^

g=lambda s:re.sub("e\+?(-?)0?","x10^\\1",s)
def f(i):

以科学计数形式转换字符串

 t=g(re.sub(r"\.[0]*e","e","%e"%i))

删除原始字符串中的0填充

 u=g(re.sub(r"(\..*)[0]*$","\\1",str(i)))

比较长度

 return t if len(u)>len(t) else u

结果

>>> [f(i) for i in [1, 20, 3000000, 400000, 0.008093, 0.007835000000000, 0.000003000000, 0.00000065, 0]]
['1', '20', '3x10^6', '400000', '0.008093', '0.007835', '3x10^-6', '6.5x10^-7', '0']
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.