首先,我是蟒蛇的新手,所以请原谅我,如果我不看树木。我的问题是读取一个巨大的浮点数文件并将它们存储在一个数组中,以便进行快速的数学后处理。
让我们假设文件看起来类似于:
/**
* This is the first stage bootloader. It is used to loader the second
* stage bootloader.
*/
# The address of this bootloader been loaded by BIOS
.equ BOOTLOADER_ADDR, 0x07c0
# The signature for bootloader.
.equ BOOT_MACHINE_SIGNATURE, 0xaa55
# The offset of the start of BPB (BIOS Parameter Block).
.equ BOOT_MACHINE_BPB_START, 0x03
# The offset of the end of BPB (BIOS Parameter Block).
.equ BOOT_MACHINE_BPB_END, 0x5a
# The offset of the end of the partition table.
.equ BOOT_MACHINE_PART_END, 0x1fe
/* The segment of disk buffer. The disk buffer MUST be 32K long and
cannot straddle a 64K boundary. */
.equ BOOT_MACHINE_BUFFER_SEG, 0x7000
.macro PRINT str
pusha
movw $\str, %si
call print
popa
.endm
.macro DUMP begin, size
movw $\begin, %si
movw $\size, %cx
call dump
.endm
.macro RESET_DISK drive
pusha
movb $\drive, %dl
movw 0x0, %ah
call reset_disk
popa
.endm
.macro READ_SECTORS drive, head, cylinder, sector, count, destination
pusha
movw $\destination, %ax
movw %ax, %es
xorw %bx, %bx
movb $\drive, %dl
movb $\head, %dh
movb $\cylinder, %ch
movb $\sector, %cl
movb $\count, %al
call read_sectors
popa
.endm
/**
* Entry point
*/
.file "boot.S"
.text
.code16
.org 0x0000
.globl _start, start;
_start:
start:
# The offset 0x0000 must be a jump to the reset of code.
jmp after_BPB
nop
. = _start + BOOT_MACHINE_BPB_START
. = _start + 4
disk_addr_packet:
.byte 0x10 # (00h) size of packet
.byte 0x00 # (01h) reserved
.word 0x0001 # (02h) number of blocks to transfer
.word 0x8000, 0x0000 # (04h) DWORD, transfer buffer
.word 0x0010, 0x0000 # (08h) QWORD, starting absolute block number
.word 0x0000, 0x0000
# (10h)
. = _start + BOOT_MACHINE_BPB_END
after_BPB:
cli # disable interrupt.
movw $BOOTLOADER_ADDR, %ax # set address expression
movw %ax, %ds
movw %ax, %es
# movw $BOOTLOADER_ADDR, %sp # stack grows down to 0x0000
PRINT message_booting
# We need make sure the BIOS supports the INT 13 extensions.
int13_ext_check:
mov $0x41, %ah
mov $0x55aa, %bx
# DL should contain the drive value. But we'd better save it.
push %dx
int $0x13
jc int13_ext_check_failed
cmpw $0xaa55, %bx
jne int13_ext_check_failed
andw $0x001, %cx # if function 42h-44h,47h,48h are supported
jz int13_ext_check_failed
jmp read_cd_content
int13_ext_check_failed:
PRINT message_no_int13_ext
jmp loop
read_cd_content:
# CHS mode : Cylinder-Head-Sector mode.
# LBA mode : Logical Block Addressing mode.
# When we use INT 13 extension, we use LBA mode in which
# the device is taken as a single large device.
PRINT message_loading_img
pop %dx
movw $disk_addr_packet, %si
movb $0x42, %ah
int $0x13
jc error_read_sectors
DUMP 0x0400, 16
jmp loop
error_read_sectors:
PRINT message_sector_read_err
jmp loop
loop:
PRINT message_halt
cli
hlt
jmp loop
message_booting:
.asciz "Booting ...\r\n"
message_halt:
.asciz "Boot Halt.\r\n"
message_no_int13_ext:
.asciz "No INT13 extension. Boot failed.\r\n"
message_loading_img:
.asciz "Loading OS image.\r\n"
message_sector_read_err:
.asciz "Sector read error.\r\n"
hexdump:
.byte 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
/**
* Write the string pointed to by %si
* Each char is wrote by using BIOS INT 0x10.
* BIOS INT 0x10:
* AH = 0x0e
* AL = Character to write.
* BH = Page Number (Should be 0)
* BL = Foreground color (Graphics Modes Only)
* When using the function, put the string address to SI. The string
* should end with 0.
*/
1:
movw $0x0001, %bx
movb $0xe, %ah
int $0x10
print:
lodsb # Loads a byte pointed by SI into AL.
cmpb $0, %al
jne 1b
ret
/**
* Print the register's value.
*
print_reg:
/**
* Dump a area of data.
* Display 8 bytes of code each line. For every 10 line will wait for any key to continue.
* SI = The start address
* CX = The size of area to dump
*/
index:
.byte '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
.byte 'A', 'B', 'C', 'D', 'E', 'F'
enter_key:
.asciz "\r\n"
1:
ret
dump:
movb $10, %dl # DL = row counter, DH = column counter.
movb $8, %dh
cld
2:
cmpw $0, %cx
je 1b
xorw %ax, %ax # clean the AX at first.
lodsb # loads the byte pointed by SI into AL.
push %ax # because AH will be used, so we save AX.
shr $4, %ax # show first 4 bits.
movw $index, %di
addw %ax, %di
movb (%di), %al
movb $0xe, %ah
movw $0x0001, %bx # Page number = 0, froeground color = 1.
int $0x10
pop %ax
andw $0x000f, %ax # show last 4 bits.
movw $index, %di
addw %ax, %di
movb (%di), %al
movb $0xe, %ah
movw $0x0001, %bx
int $0x10
movb $' ', %al # display a space
movb $0xe, %ah
movw $0x0001, %bx
int $0x10
dec %cx
dec %dh
jnz 2b
PRINT enter_key
movb $8,%dh
jmp 2b
/**
* Reset the disk controller, let it go to the first sector.
* BIOS INT 0x13
* AH = 0x00
* DL = Drive to reset.
* Return:
* AH = Status code.
* CF = Clear if success, set if failure.
*/
reset_disk:
int $0x13
jc reset_disk
ret
/**
* Read sectors into memory
* BIOS INT 0x13
* AH = 0x02
* AL = Numbers of sectors to read.
* CH = Low eight bits of cylinder number.
* CL = Sector Number Bits 0-5. Bits 6-7 are for hard disks only.
* DH = Head number.
* DL = Drive number (Bit 7 set for hard disk)
* ES:BX = Buffer to read sector to
* Return
* AH = Status code
* AL = Number of sectors read
* CF = Set if failure, cleaned if successful.
*/
read_sectors:
int $0x13
jc read_sectors
ret
.fill 0x1fe - (. - _start) ,1,0
.org _start + BOOT_MACHINE_PART_END
.word BOOT_MACHINE_SIGNATURE
这里有4(nb)个14(nk)个浮点数。我希望它们被安排在数组元素[nb] [nk]中,以便我可以轻松地访问块的某些浮点数。
以下是我认为的样子,但它根本不起作用:
!!
-3.2297390 0.4474691 3.5690145 3.5976372 6.9002712 7.7787466 14.2159269 14.3291490
16.7660723 17.1258704 18.9469059 19.1716808 20.0700721 21.4088414
-3.2045361 0.4123081 3.5625981 3.5936954 6.8901539 7.7543415 14.2764611 14.3623976
16.7955934 17.1560337 18.9527369 19.1251184 20.0700709 21.3515145
-3.2317597 0.4494166 3.5799182 3.6005429 6.8838705 7.7661897 14.2576455 14.3295731
16.7550357 17.0986678 19.0187779 19.1687722 20.0288587 21.3818250
-3.1921346 0.3949598 3.5636878 3.5892085 6.8833690 7.7404542 14.3061281 14.3855389
16.8063645 17.1697110 18.9549920 19.1134580 20.0613223 21.3196066
如果有一些想法和建议会很棒。谢谢!
编辑:
这里是一个数据文件,其中数字跟在一起,在块nb后没有明确的分隔符。这里是nb = 2且nk = 160。如何在每个第160个数字后拆分浮点数?
nb=4
nk=14
with open("datafile") as file:
elements = []
n = 0
while '!!' not in file:
while n <= (nb-1):
elements.append([])
current = map(float,file.read().split()) # here I would need something to assure only 14 (nk) floats are read in
elements[n].append(current)
n += 1
print(elements[0][1])
答案 0 :(得分:1)
这应该有效:
elements = []
with open("datafile") as file:
next(file)
for line in file:
elements.append([float(x) for x in line.split()])
next(line)
读取第一行。然后for line in file:
遍历所有其他行。列表推导[float(x) for x in line.split()]
遍历由空格分割的行中的所有条目。最后,elements.append()
将此列表附加到elements
,这将成为您可以称为2D数组的列表列表。
访问第一行中的第一个条目:
>>> elements[0][0]
-3.229739
或最后一行中的最后一个条目:
>>> elements[3][13]
21.319606
或者:
>>> elements[-1][-1]
21.319606
这会将文件读入列表列表,而不会将换行符视为特殊符号:
nb = 2
nk = 160
with open("datafile") as fobj:
all_values = iter(x for x in fobj.read().split())
next(all_values)
elements = []
for x in range(nb):
elements.append([float(next(all_values)) for counter in range(nk)])
如果您喜欢嵌套列表推导:
with open("datafile") as fobj:
all_values = iter(x for x in fobj.read().split())
next(all_values)
elements = [[float(next(all_values)) for counter in range(nk)] for x in range(nb)]