标题: [文本处理] [已解决]批处理如何对含科学计数数字的txt批量修改? [打印本页]
作者: alexwxcong 时间: 2010-5-1 20:54 标题: [已解决]批处理如何对含科学计数数字的txt批量修改?
我有如下内容的大量txt文件
2.0000000000000001e-001
0.0000000000000000e+000
0.0000000000000000e+000
-2.0000000000000001e-001
1.6695009999999998e+005
2.8049900000000001e+004
需要对科学计数改为正常数字,即如下
0.2
0
0
-0.2
166950.09999999998
28049.900000000001
[ 本帖最后由 alexwxcong 于 2010-5-2 20:30 编辑 ]
作者: alexwxcong 时间: 2010-5-1 20:56
诚请高手帮忙,俺琢磨了一天了,实在水平太低
作者: cjiabing 时间: 2010-5-1 21:34
不懂数学,哈哈,不懂科学计数!~不过应该不难,只是麻烦点
作者: alexwxcong 时间: 2010-5-1 21:43
e-001就是前面的2.0000000000000001乘以0.1
e+000数字不变
e+005就是前面的1.6695009999999998乘以100000
e+004就是前面的2.8049900000000001乘以10000
作者: yangfengoo 时间: 2010-5-1 23:26
关键是P难以处理小数
作者: hanyeguxing 时间: 2010-5-1 23:26
1,“大量txt文件”是否指多个txt文本?
2,“含科学计数数字”,那么文本中是否还含有其他内容?
如果有,区分规则是什么?
3,“含科学计数数字”的构成规则是什么?
-2.0000000000000001e-001都是这样的模式?
作者: sgaizxt001 时间: 2010-5-2 00:36
我的漏洞好多,编辑掉。看看我师傅的代码先
[ 本帖最后由 sgaizxt001 于 2010-5-2 04:26 编辑 ]
作者: namejm 时间: 2010-5-2 01:54
1、小数点后的位数是否只保留有16位?
2、是否所有的正数都没有前缀+而只有负数才有前缀-?
4、e后的004、005之类的是否有可能会达到999?请给出它的范围。
作者: hanyeguxing 时间: 2010-5-2 03:11
1,代码没有优化,所以速度。。。100行转换实测耗时2.46妙,汗一个先
2,要求所有文本内只存在科学记数的内容,不含其他内容。
3,批处理放在同一目录下,新生成的文本将放到test子目录中。
4,e后的数字允许范围为000到999
5,小数部分最多保留16位(按楼主的要求)
6,数字小于0.0000000000000001时将被近似为0.0000000000000001- @echo off&setlocal enabledelayedexpansion
- if not exist "test\" md test
- for %%z in (*.txt) do (
- for /f "usebackq tokens=1,2* delims=e." %%a in ("%%z") do (
- set a=%%a&set b=%%b&set c=%%c
- set d=!c:~1!
- for %%d in (0 0) do if !d:~0^,1!==0 set d=!d:~1!
- if !a:~0^,1!==- set n=-&set a=!a:~1!
- if !a:~0^,1!==0 (echo.0) else (
- set m=!a!!b!
- if !c:~0^,1!==+ (
- if !d! lss 16 (
- set/a d+=1
- for %%d in (!d!) do set m=!m:~0,%%d!.!m:~%%d!
- ) else (
- set/a a=d-16
- for /l %%d in (1,1,!a!) do set z=!z!0
- set m=!m!!z!
- )
- ) else (
- set/a a=d-1
- for /l %%d in (1,1,!a!) do set z=!z!0
- set m=0.!z!!m!&set m=!m:~0,18!
- )
- echo.!m!|find ".">nul 2>nul&&call:f !m!
- echo.!n!!m!
- )
- set n=&set z=))>test\%%z
- exit
- :f
- set f=%1
- if %f%==0.0000000000000000 set f=0.0000000000000001
- for /f "tokens=1,2 delims=." %%a in ("%f%") do set a=%%a&set b=.%%b
- :g
- if not "!b:~%g%,1!"=="" set/a g+=1&goto:g
- for /l %%a in (1,1,%g%) do if not !b:~-%%a^,1!==0 (
- set/a h=%%a-1
- if not !h!==0 for %%b in (!h!) do set "b=!b:~0,-%%b!"
- goto:e)
- :e
- set m=%a%%b%&set g=
- if %m:~-1%==. set m=%m:~0,-1%
复制代码
[ 本帖最后由 hanyeguxing 于 2010-5-2 03:37 编辑 ]
作者: namejm 时间: 2010-5-2 03:35
大致的思路应当是这样的:
把数值的正负号、整数部分、分数部分、指数部分和指数的正负号分别保存为变量,然后,把指定长度的纯0字符串拼接起来,拼接的规律为:若指数符号为负,则把纯0字符串放到整数部分之前;若指数符号为正,则把纯0字符串放到小数部分之后。把纯0字符串拼接之后,再根据指数部分把小数点位置做相应的移动,最后,把所有部分拼接起来,去掉整数部分之前和小数部分之后的纯0字符串即可。
虽然思路比较简单,但是我居然发现在for语句中使用如下代码的时候出错了,如果把其中截取字符串的负号去掉,则该语句正常,百思不得其解:- set num=!str_int:~0,-%num_point%!.!str_int:~%num_point%!!dec!
复制代码
9楼的代码之所以慢,是因为使用了管道符号,频繁的I/O操作势必会拖慢速度。
作者: hanyeguxing 时间: 2010-5-2 03:44
1,本批处理使用%%~fd扩展删除0,所以批处理所在路径中最好别用敏感字符
2,本批处理直接修改原文件,所以运行前推荐先将所有原文件备份分:- @echo off
- for %%z in (*.txt) do (
- (for /f "usebackq tokens=1,2* delims=e." %%a in ("%%z") do (
- setlocal enabledelayedexpansion
- set a=%%a&set b=%%b&set c=%%c&set d=!c:~1!
- for %%d in (0 0) do if !d:~0^,1!==0 set d=!d:~1!
- if !a:~0^,1!==- set n=-&set a=!a:~1!
- if !a:~0^,1!==0 (echo.0) else (
- set m=!a!!b!
- if !c:~0^,1!==+ (
- if !d! lss 16 (set/a d+=1&for %%d in (!d!) do set m=!m:~0,%%d!.!m:~%%d!) else (
- set/a a=d-16&for /l %%d in (1,1,!a!) do set z=!z!0
- set m=!m!!z!
- )
- ) else (
- set/a a=d-1&for /l %%d in (1,1,!a!) do set z=!z!0
- set m=0.!z!!m!&set m=!m:~0,18!
- if !m!==0.0000000000000000 set m=0.0000000000000001
- )
- if not "!m:.=!"=="!m!" set "m=!m:0= !"&for /f "delims=" %%d in ("!m!") do set m=%%~fd&set "m=!m:%cd%\=!"&set "m=!m: =0!"
- echo.!n!!m!)
- endlocal))>"%%z_"
- del /q "%%z"
- ren "%%z_" "%%z"
- )
复制代码
至于:原帖由 namejm 于 2010-5-2 03:35 发表
虽然思路比较简单,但是我居然发现在for语句中使用如下代码的时候出错了,如果把其中截取字符串的负号去掉,则该语句正常,百思不得其解:
代码:set num=!str_int:~0,-%num_point%!.!str_int:~%num_point%!!dec!
因为没有看到完整代码,个人猜测是这个原因:http://bbs.bathome.net/thread-7629-4-1.html的46楼
[ 本帖最后由 hanyeguxing 于 2010-5-2 09:02 编辑 ]
作者: alexwxcong 时间: 2010-5-2 11:16
谢谢hanyeguxing ,我先备份一个试过了,按你的方法好像是可以,谢谢啊
作者: alexwxcong 时间: 2010-5-2 11:19
原帖由 namejm 于 2010-5-2 01:54 发表
1、小数点后的位数是否只保留有16位?
2、是否所有的正数都没有前缀+而只有负数才有前缀-?
4、e后的004、005之类的是否有可能会达到999?请给出它的范围。
1,小数点后的位数可以不用太多,8位就够了
2,前缀可以不用考虑,可以直接删除E前的那个数字
3,E后面的004/005这种不会超过010
作者: terse 时间: 2010-5-2 11:25
004/005 是否根据+-确定小数点前移或后移4位或5位?如是这样可否移动这个点呢
作者: alexwxcong 时间: 2010-5-2 11:32
恩,其实科学计数就是移动小数点
作者: 随风 时间: 2010-5-2 12:35
虽然思路比较简单,但是我居然发现在for语句中使用如下代码的时候出错了,如果把其中截取字符串的负号去掉,则该语句正常,百思不得其解:
能给出出错部分的完整代码吗
作者: CUer 时间: 2010-5-2 13:20
精度比较低- @echo off
- for /f %%a in (a.txt) do (
- math.exe %%a
- )
复制代码
作者: 随风 时间: 2010-5-2 13:25
不知道对不对
:- @echo off & setlocal enabledelayedexpansion
- for /f "tokens=1,2 delims=e" %%i in (a.txt) do (
- set var=%%j
- for /f "tokens=1,2 delims=." %%a in ("%%i") do (
- set z=%%a&set x=%%b00000000000000000
- )
- set f=&set h=
- if "!var:~0,1!"=="-" set f=a
- set var=!var:~1!
- for /f "tokens=* delims=0" %%a in ("!var!") do (
- if "!f!"=="" (set z=!z!!x:~0,%%a!&set x=!x:~%%a!) else (
- if "!z:~0,1!"=="-" set z=!z:-=!&set h=-
- set z=0000000000000000000!z!
- set x=!z:~-%%a!!x!
- set z=!z:~0,-%%a!
- for /f "tokens=* delims=0" %%c in ("!z!") do (
- if "%%c"=="" set z=0
- )
- )
- )
- echo !h!!z!.!x:~0,8!
- )
- pause
复制代码
作者: CUer 时间: 2010-5-2 13:47
精度非常接近了- gawk "{printf(\"%.12f\n\",$0)}" a.txt | gawk "{gsub(/0+$/,\"\");gsub(/\.$/,\"\")}1"
复制代码
作者: alexwxcong 时间: 2010-5-2 14:48
原帖由 alexwxcong 于 2010-5-2 11:16 发表
谢谢hanyeguxing ,我先备份一个试过了,按你的方法好像是可以,谢谢啊
不好意思啊,发现一个问题,就是我这种txt文件大概有3千多个,其中差不多1000左右是正常的,没有科学计数的,如果按照hanyeguxing兄这个代码执行,会将其中原本正常的变成这样
0
0
0
0
0.829499998926702
0.3405
原本是这样的
0.2
0
0
-0.2
82949.9998926702
34050
作者: alexwxcong 时间: 2010-5-2 16:20
原帖由 随风 于 2010-5-2 13:25 发表
不知道对不对
echo off & setlocal enabledelayedexpansion
for /f "tokens=1,2 delims=e" %%i in (a.txt) do (
set var=%%j
for /f "tokens=1,2 delims=." %%a in ("%%i") do (
set z=%%a&set x ...
我的不是在一个txt里面,是有数千个txt
作者: namejm 时间: 2010-5-2 17:03
用10楼的思路,得到如下代码(仅处理一个文件):
- @echo off
- setlocal enabledelayedexpansion
- set str_zero=
- for /l %%i in (1,1,10) do set str_zero=0!str_zero!
- for /f "tokens=1-3 delims=.e" %%i in (test.txt) do (
- set int=%%i
- set char_int=
- if "!int:~0,1!"=="-" (
- set char_int=-
- set int=!int:~1!
- )
- set dec=%%j
- set e=%%k
- set char_e=!e:~0,1!
- set e=!e:~1!
- call :cut_zero_left !e!
- if "!char_e!"=="+" (
- set str_dec=!dec!%str_zero%
- call set num=!int!%%str_dec:~0,!num_NoLeftZero!%%.%%str_dec:~!num_NoLeftZero!%%
- ) else (
- set str_int=%str_zero%!int!
- call set num=%%str_int:~0,-!num_NoLeftZero!%%.%%str_int:~-!num_NoLeftZero!%%!dec!
- )
- for /f "tokens=1* delims=." %%x in ("!num!") do (
- if "!char_e!"=="-" (
- call :cut_zero_left %%x
- set num_NoRightZero=%%y
- )
- if "!char_e!"=="+" (
- call :cut_zero_right %%y
- set num_NoLeftZero=%%x
- )
- )
- if defined num_NoRightZero (
- echo !char_int!!num_NoLeftZero!.!num_NoRightZero!
- ) else echo !char_int!!num_NoLeftZero!
- )
- pause
- exit
-
- :cut_zero_left
- :: 去除字符串最左侧的纯0字符串
- set num_NoLeftZero=0
- for /f "tokens=1* delims=0" %%i in ("%1") do set num_NoLeftZero=%%i
- goto :eof
-
- :cut_zero_right
- :: 去除字符串最右侧的纯0字符串
- set num_NoRightZero=%1
- :loop
- if "%num_NoRightZero:~-1%"=="0" (
- set num_NoRightZero=!num_NoRightZero:~0,-1!
- if defined num_NoRightZero goto loop
- )
- goto :eof
复制代码
经测试,100行数据耗时约1.5秒,测试环境为:1.6GHZ主频、512M内存、XP_SP3系统。
若楼主觉得处理结果完全符合你的需要,我将改写代码,以适应成百上千个txt文档的情况;若有其他需求,请继续提出。
10楼提到的那个问题,是因为没有使用 call 来延迟变量的扩展导致的,和字符串截取长度超过字符串本身长度无关。
作者: namejm 时间: 2010-5-2 17:07
原帖由 alexwxcong 于 2010-5-2 14:48 发表
不好意思啊,发现一个问题,就是我这种txt文件大概有3千多个,其中差不多1000左右是正常的,没有科学计数的
到底是某些文本中科学计数和常规计数混杂的,还是每个文档要么全是科学计数要么是常规计数?请说明白一点。
到目前为止,跟帖已经达到两页,请楼主把所有的需求全部更新到顶楼,否则,别人要准确全面地了解你的本意,还得从头到尾全部看一遍帖子,其间思路一变再变,恐怕没几个人有耐心把你帮到底。
作者: alexwxcong 时间: 2010-5-2 17:52
哦,谢谢,是这样的,每个txt内容只有上面贴出的6行,txt文件的数量大概是3千多,
目的是,把全部的txt转换成标准的常规数字
现状是两种txt都有,有些是常规数字,有些是科学计数法,不存在一个txt里面既有常规数字又有科学计数法的情形
思路没变,只不过没表述清楚
[ 本帖最后由 alexwxcong 于 2010-5-2 17:54 编辑 ]
作者: 随风 时间: 2010-5-2 18:28
似乎楼主没看见23楼的帖子的最后两行,又或是认为那与他无关,只要不是解决我问题的字我坚决不看 ^_^
也怀疑楼主有没有测试18楼的代码。
作者: namejm 时间: 2010-5-2 18:38
哈哈,还是随风18楼的思路简洁,速度更快,可惜楼主一直没有把已知条件交代精确,老是想兼容各种特殊情况,反倒搞复杂了。
我估计楼主在截取小数点后8位之后,可能还会要求四舍五入、去掉最后的纯0字符串之类的,唉,亲爱的楼主,你这样像挤牙膏一样一次来一点,何时是个尽头啊?
作者: netbenton 时间: 2010-5-2 19:16
有点不明白,楼主一楼的例子,为什么第一行和最后一行的后面都有一个1,但是结果只有最后一行保留了这个1,是根据什么呢?
我也来个,这里你看不到if- @echo off&setlocal enabledelayedexpansion
- set file=aaa.txt
- for /f "delims=.e tokens=1-4" %%a in (%file%) do (
- for /f "delims=0 tokens=1*" %%x in ("%%c") do (
- set/a dot=%%y+0
- set -=0000000000%%a
- set +=%%b
- for /f "tokens=1,2" %%1 in ("%%x !dot!") do (
- set %%1=!%%1:~,%%1%%2!.!%%1:~%%1%%2!
- )
- for /f "tokens=*" %%o in ("!-:0= !!+:0= !") do (
- set str=-%%~nxo.
- set str=!str:-.=-0.!
- set str=!str: =0!
- echo;结果:!str:~1,-1!
- )
-
- )
- )
- pause
复制代码
[ 本帖最后由 netbenton 于 2010-5-2 19:25 编辑 ]
作者: alexwxcong 时间: 2010-5-2 20:21
因为我开始没完全说清楚,让各位费解了,实在对不住,在此表示歉意,我已经另行找了一个搜索所有科学计数法的txt,另存到一个文件夹,在用hanyeguxing兄的方法就可以解决了,在这谢谢了,特此结贴。
作者: hanyeguxing 时间: 2010-5-2 20:31
根据楼主要求:
1,移位数字范围为000到015
2,允许科学记数与普通数字(非16进制)混排
3,100行测试,运行时间小于0.08秒
4,所有科学记数转换的数字只精确到小数8位(未使用4舍5入)
5,对于小于0.00000001的数字,精确到0.00000001- @echo off
- for %%a in (*.txt) do (
- (for /f "usebackq delims=" %%b in ("%%a") do (
- setlocal enabledelayedexpansion
- set b=%%b
- if !b:~18^,1!==e set a==
- if !b:~19^,1!==e set a==
- if not defined a (echo.%%b) else (
- for /f "tokens=1,2* delims=e." %%c in ("%%b") do (
- set c=%%c&set d=%%d&set e=%%e&set f=!e:~2!
- if !f:~0^,1!==0 set f=!f:~1!
- if !c:~0^,1!==- set g=-&set c=!c:~1!
- if !c:~0^,1!==0 (echo.0) else (
- set h=!c!!d!
- if !e:~0^,1!==+ (
- set/a f+=1&for %%f in (!f!) do set h=!h:~0,%%f!.!h:~%%f!
- ) else (
- set/a f-=1&for /l %%f in (1,1,!f!) do set i=!i!0
- set h=0.!i!!h!
- )
- for /f "tokens=1* delims=." %%f in ("!h!") do set f=%%g&set h=%%f.!f:~0,8!
- if !h!==0.00000000 set h=0.00000001
- if not "!h:.=!"=="!h!" set "h=!h:0= !"&set "h=!h:.=#!"&for /f "delims=" %%f in ("!h!") do set h=%%~ff&set "h=!h:%cd%\=!"&set "h=!h:#=.!"&set "h=!h: =0!"
- if !h:~-1!==. set h=!h:~0,-1!
- echo.!g!!h!)))
- endlocal))>"%%a_"
- del /q "%%a"
- ren "%%a_" "%%a")
复制代码
结贴时,请修改主题并在前面加[已解决]
[ 本帖最后由 hanyeguxing 于 2010-5-2 20:36 编辑 ]
作者: terse 时间: 2010-5-3 15:00
- @echo off&setlocal enabledelayedexpansion
- set "l=0000000000"
- for /f "tokens=1,2 delims=e" %%i in (a.txt) do (
- set "str=%%i"
- if "%%j" neq "" (
- set /a "i=%%j%%1000"
- if !i! neq 0 (
- if !i! lss 0 (
- for /f "tokens=1,2 delims=." %%a in ("%%i") do (
- set "str=%%a"
- if %%a lss 0 (set j=-0.)else set "j=0."
- set "str=%l%!str:-=!"
- set "b=%%b"
- for %%c in (!i!) do set "str=!j!!str:~%%c!!b:~,%%c!"
- )
- ) else (
- for /f "tokens=1,2 delims=." %%a in ("%%i") do (
- set "str=%%b"
- for %%c in (!i!) do set "str=%%a!str:~,%%c!.!str:~%%c!"
- )
- )
- )
- )
- if "!str:0=!" neq "." (echo !str!)else echo 0
- )
- pause
复制代码
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |