7
\$\begingroup\$

Write the shortest function you can that takes two binary-coded decimal integers and a character indicating an arithmetic operation to perform and return the result.

Input Specification
You will be passed two 32-bit bit patterns representing unsigned BCD integers. In C or Java, for example, you would be passed an int (unsigned, if you prefer). The third argument to your function will be a single character denoting what operation to perform. If your language requires fixed return sizes, return a 32-bit result and ignore overflow. Your return value should also be encoded as a BCD.

You should support +, -, *, /, and %. For subtraction, the first argument is the minuend and the second argument is the subtrahend. For division and modulo, the first argument is the quotient and the second is the divisor.

Example

bcd(0x00000127, 0x00000003, '+') => 0x00000130 // NOT 0x0000012A
\$\endgroup\$

4 Answers 4

4
\$\begingroup\$

AMD64 machine language on Linux, 51 44 41 bytes

0:  6a 00                   push   0x0
2:  57                      push   rdi             ; push 1st arg onto stack
3:  df 24 24                fbld   TBYTE PTR [rsp] ; copy to x87 stack
6:  5f                      pop    rdi
7:  56                      push   rsi             ; push 2nd arg onto stack
8:  df 24 24                fbld   TBYTE PTR [rsp] ; copy to x87 stack
b:  83 fa 2a                cmp    edx,0x2a        ; multiplication?
e:  74 0b                   je     1b <_mul>
10: 83 fa 2d                cmp    edx,0x2d        ; subtraction?
13: 74 0a                   je     1f <_sub>
15: 78 0a                   js     21 <_add>       ; if the comparison is negative, must be addition
17: de f9                   fdivp  st(1),st
19: eb 08                   jmp    23 <L>
000000000000001b <_mul>:
1b: de c9                   fmulp  st(1),st
1d: eb 04                   jmp    23 <L>
000000000000001f <_sub>:
1f: d9 e0                   fchs                   ; flip sign of value on top of x87 stack (subtraction)
0000000000000021 <_add>:
21: de c1                   faddp  st(1),st
0000000000000023 <L>:
23: df 34 24                fbstp  TBYTE PTR [rsp] ; transfer from x87 stack to integer stack
26: 58                      pop    rax             ; transfer result to rax
27: 5a                      pop    rdx
28: c3                      ret 

Today I learned the x87 floating point unit has hardware support for packed BCD arithmetic. To Try it online! compile and run the following C program.

(*f)()="\x6A\x00\x57\xDF\x24\x24\x5F\x56\xDF\x24\x24\x83\xFA\x2A\x74\x0B\x83\xFA\x2D\x74"
"\x0A\x78\x0A\xDE\xF9\xEB\x08\xDE\xC9\xEB\x04\xD9\xE0\xDE\xC1\xDF\x34\x24\x58\x5A\xC3";

int main(){
 printf("%08x + %08x = %08x\n", 0x00000127, 0x00000003,f(0x00000127, 0x00000003, '+'));
 printf("%08x * %08x = %08x\n", 0x00000127, 0x00000003,f(0x00000127, 0x00000003, '*'));
 printf("%08x / %08x = %08x\n", 0x00000127, 0x00000003,f(0x00000127, 0x00000003, '/'));
 printf("%08x - %08x = %08x\n", 0x00000127, 0x00000003,f(0x00000127, 0x00000003, '-'));
}
\$\endgroup\$
2
\$\begingroup\$

Python - 47 chars

bcd=lambda*a:"0x%08d"%eval("%x%s%x"%(a*2)[::2])

tests

>>> print bcd(0x00000127, 0x00000003, '+')
0x00000130
>>> print bcd(0x00000127, 0x00000003, '*')
0x00000381
>>> print bcd(0x00000127, 0x00000003, '/')
0x00000042
>>> print bcd(0x00000127, 0x00000003, '-')
0x00000124
\$\endgroup\$
2
  • \$\begingroup\$ I guess the question says we have to return as a BCD? codepad.org/6SyEB7DJ \$\endgroup\$ Commented Feb 11, 2011 at 9:16
  • \$\begingroup\$ @Dogbert, perhaps, but it doesn't really make sense to me to talk about passing in / returning a BCD. BCD here is just painting "0x" in front of the decimal representation of the number, which is quite different from using BCD numbers in assembler \$\endgroup\$ Commented Feb 11, 2011 at 12:03
1
\$\begingroup\$

Windows PowerShell, 54 56 69

filter f($a,$b,$o){'0x'+("{0:x}$o{1:x}"-f+$a,+$b|iex)}

A bit cheating, I guess, but the output very well works as input again. I.e., PowerShell doesn't care whether it's a string or actual numeric literal there.

Test:

> f 0x127 0x3 +
0x130

History:

  • 2011-02-11 10:35 (69) – First attempt.
  • 2011-02-11 10:36 (56) – Going easy on the extra zeroes.
  • 2011-02-11 10:41 (54) – filter is shorter.
\$\endgroup\$
1
\$\begingroup\$

JavaScript ES6, 61 bytes

(a,b,y)=>0|'0x'+~~eval([a,b].map(t=>+t.toString(16)).join(y))
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.