2011大纽约区域赛试题 Decoding EDSAC Data 解题报告
2015-04-15 22:11
295 查看
2011大纽约程序设计竞赛,D题 Decoding EDSAC Data(题目链接)。
The EDSAC was programmed using a very simple assembly language: a single letter opcode followed by an unsigned decimal address, followed by the the letter 'F' (for full word) or 'D' (for double word). For example, the instruction "A 128 F" would mean "add the full word at location 128 to the accumulator", and would be assembled into the 17-bit binary value, 11100000100000000, consisting of a 5-bit opcode (11100="add"), an 11-bit operand (00010000000 = 128), and a single 0 bit denoting a full word operation (a 1 bit would indicate a double word operation).
Although arithmetic on the EDSAC was fixed point two's complement binary, it was not mere intger arithmetic (as is common with modern machines). The EDSAC hardware assumed a binary point between the leftmost bit and its immediate successor. Thus the hardware could handle only values in the range -1.0 ≤ x < 1.0. For example:
As you can see, the largest possible positive value was:
01111111111111111 = 0.9999847412109375
and the smallest possible positive value was:
00000000000000001 = 2-16 = 0.0000152587890625
(This also happens to be the increment between successive values on the EDSAC).
By a curious coincidence(or an elegant design decision), the opcode for the add operation(11100) was the same as the teleprinter code for the letter 'A'. The opcode for subtract was the same as the teleprinter code for 'S'(01100), and so on. This simplified the programming for the assembler (which, incidentally, was a mere 31 instructions long). The EDSAC teleprinter alphabet was "PQWERTYUIOJ#SZK*?F@D!HNM&LXGABCV" (with 'P'=00000, 'Q'=00001, and so on, up to 'V'=11111)
Unfortunately, the EDSAC assembler had no special directives for data values. On the other hand, there was no reason that ordinary instructions couldn't be used for this, thus, an EDSAC programmer desiring to reserve space for the constant ¾ (represented as 01100000000000000) would use the instruction "S O F" and for ⅓ (which is approximately represented as 00101010101010101) "T 682 D", and so on.
Your job is to write a program that will translate EDSAC instructions into the appropriate decimal fractions.
Input
The first line of input contains a single integer P ( 1 ≤ P ≤ 1000 ) which is the number of data sets that follow. Each data set is a single line that contains N (the dataset number), followed by a space, followed by an EDSAC instruction of the form: c□d□s, where c is a single character in the EDSAC alphabet, d is an unsigned decimal number (0 ≤ d < 211), and s is either a 'D' or 'F'. Note: □ represents a single space.
Output
For each data set there is one line of output. It contains the data set number (N) followed by a single space, followed by the exact decimal fraction represented by the by the EDSAC instruction, including a minus sign (for negative values). The format for the decimal fraction is:
这一题,我是直接用机器中的二进制来做的,一位一位地判断。前五位(细分成第一位,接下来的4位),中间11位,后一位,分开来处理。另外,正负也分别处理。
C语言源代码如下:
D ⋅ Decoding EDSAC Data
The world's first full-scale, stored-program, electronic, digital computer was the EDSAC (Electronic Delay Storage Automatic Calculator). The EDSAC had an accumulator-based instruction set, operating on 17-bit words(and 35-bit double words), and used a 5-bit teletypewriter code for input and output.The EDSAC was programmed using a very simple assembly language: a single letter opcode followed by an unsigned decimal address, followed by the the letter 'F' (for full word) or 'D' (for double word). For example, the instruction "A 128 F" would mean "add the full word at location 128 to the accumulator", and would be assembled into the 17-bit binary value, 11100000100000000, consisting of a 5-bit opcode (11100="add"), an 11-bit operand (00010000000 = 128), and a single 0 bit denoting a full word operation (a 1 bit would indicate a double word operation).
Although arithmetic on the EDSAC was fixed point two's complement binary, it was not mere intger arithmetic (as is common with modern machines). The EDSAC hardware assumed a binary point between the leftmost bit and its immediate successor. Thus the hardware could handle only values in the range -1.0 ≤ x < 1.0. For example:
Value | Binary Representation |
---|---|
-1.0 | 10000000000000000 |
½ | 01000000000000000 |
¾ | 01100000000000000 |
-½ | 11000000000000000 |
01111111111111111 = 0.9999847412109375
and the smallest possible positive value was:
00000000000000001 = 2-16 = 0.0000152587890625
(This also happens to be the increment between successive values on the EDSAC).
By a curious coincidence(or an elegant design decision), the opcode for the add operation(11100) was the same as the teleprinter code for the letter 'A'. The opcode for subtract was the same as the teleprinter code for 'S'(01100), and so on. This simplified the programming for the assembler (which, incidentally, was a mere 31 instructions long). The EDSAC teleprinter alphabet was "PQWERTYUIOJ#SZK*?F@D!HNM&LXGABCV" (with 'P'=00000, 'Q'=00001, and so on, up to 'V'=11111)
Unfortunately, the EDSAC assembler had no special directives for data values. On the other hand, there was no reason that ordinary instructions couldn't be used for this, thus, an EDSAC programmer desiring to reserve space for the constant ¾ (represented as 01100000000000000) would use the instruction "S O F" and for ⅓ (which is approximately represented as 00101010101010101) "T 682 D", and so on.
Your job is to write a program that will translate EDSAC instructions into the appropriate decimal fractions.
Input
The first line of input contains a single integer P ( 1 ≤ P ≤ 1000 ) which is the number of data sets that follow. Each data set is a single line that contains N (the dataset number), followed by a space, followed by an EDSAC instruction of the form: c□d□s, where c is a single character in the EDSAC alphabet, d is an unsigned decimal number (0 ≤ d < 211), and s is either a 'D' or 'F'. Note: □ represents a single space.
Output
For each data set there is one line of output. It contains the data set number (N) followed by a single space, followed by the exact decimal fraction represented by the by the EDSAC instruction, including a minus sign (for negative values). The format for the decimal fraction is:
sb.ddd..., where
sis an optional minus sign,
bis either a 1 or 0, and d is any decimal digit (0-9). There must be at least 1 and at most 16 digits after the decimal point. Trailing zeros in the fraction must be suppressed.
Sample Input | Sample Output |
---|---|
13 1 P 0 F 2 I 0 F 3 & 0 F 4 ? 0 F 5 Q 1228 D 6 P 0 D 7 V 2047 D 8 * 2047 D 9 ? 0 D 10 P 256 F 11 V 1536 F 12 T 682 D 13 T 54 F | 1 0.0 2 0.5 3 -0.5 4 -1.0 5 0.0999908447265625 6 0.0000152587890625 7 -0.0000152587890625 8 0.9999847412109375 9 -0.9999847412109375 10 0.0078125 11 -0.015625 12 0.3333282470703125 13 0.31414794921875 |
C语言源代码如下:
#include <stdio.h> #include <stdlib.h> #include <assert.h> #include <string.h> const char * code = "PQWERTYUIOJ#SZK*?F@D!HNM&LXGABCV"; int main (void) { int testcases; int testcase; char firstpart; int secondpart; char thirdpart; int i; unsigned short number; long long result; int sign; long long current; char final[100];; scanf( "%d", &testcases ); while ( testcases -- ) { scanf( "%d %c %d %c", &testcase, &firstpart, &secondpart, &thirdpart ); for ( i = 0; code[i] != '\0' ; i ++ ) { if ( code[i] == firstpart ) break; } assert( code[i] != '\0' ); if ( i >= 0x10 ) { number = i - 0x10 ; sign = -1; } else { number = i; sign = 1; } number <<= 12; number += (secondpart << 1); if ( thirdpart == 'D' ) number ++; result = 0; current = 152587890625; if ( sign > 0 ) { for ( i = 1 ; i <= 16 ; i ++ ) { if ( (number & 1 ) == 1 ) { result += current; } number >>= 1; current <<= 1; } #ifdef _WIN32 sprintf( final, "0.%016I64d", result ); #else sprintf( final, "0.%016lld", result ); #endif } else { number --; for ( i = 1 ; i <= 16 ; i ++ ) { if ( (number & 1 ) == 0 ) { result += current; } number >>= 1; current <<= 1; } #ifdef _WIN32 sprintf( final, "-0.%016I64d", result ); #else sprintf( final, "-0.%016lld", result ); #endif } if ( !strcmp(final, "-0.0000000000000000" ) ) strcpy( final, "-1.0" ); else { if ( sign > 0 ) { for ( i = 17; i > 2 ; i -- ) { if ( final[i] == '0' ) final[i] = '\0'; else break; } } else { for ( i = 18; i > 3 ; i -- ) { if ( final[i] == '0' ) final[i] = '\0'; else break; } } } printf( "%d %s\n", testcase, final ); } return EXIT_SUCCESS; }
相关文章推荐
- 2011大纽约区域赛试题 Decoding EDSAC Data 解题报告
- HDOJ 4239 - Decoding EDSAC Data 模拟
- HDU_4239_Decoding EDSAC Data(模拟)
- 济南-1101试题解题报告
- 北大ACM试题分类 - 实时更新我所有的解题报告链接
- Regional 2011, Asia - Kuala Lumpur 解题报告
- Codevs5230【三校联考试题】 猴子(重庆一中高2018级信息学竞赛测验8) 解题报告
- [Usaco2011][bzoj2442][洛谷2527]修剪草坪解题报告(dp,贪心,单调队列)
- 【解题报告】2011 Multi-University Training Contest 1-Host by HNU
- [国家集训队2011]种树&nbsp;解题报告
- NOIP2011普及组 瑞士轮(重庆一中高2018级信息学竞赛测验4) 解题报告
- BZOJ 2527 [Poi 2011] 整体二分 解题报告
- 第六届蓝桥杯校园选拔赛试题---派遣敢死队 解题报告
- 洛谷 1313||NOIP 2011 计算系数 二项式定理 解题报告
- 区域赛套题 第二场解题报告
- 北大ACM试题分类 - 实时更新我所有的解题报告链接
- Facebook Hacker Cup 2014 Qualification Round 竞赛试题 Square Detector 解题报告
- HCPC 2011 Spring Online Contest解题报告
- noip2011提高组day1+day2解题报告
- 解题报告:LeetCode Find Median from Data Stream(查找中位数)