University of California at Berkeley
College of Engineering
Department of Electrical Engineering and Computer Science

CS61C, Summer 2010

HW 5 - Floating Point

Due Tuesday, July 13, 2010 @ 11:59pm

Getting Started

Copy the contents of ~cs61c/hw/05 to a suitable location in your home directory.

cp -r ~cs61c/hw/05 ~/hw5


Submit your solution by creating a directory named hw5 that contains the file fp.c. (Note that capitalization matters in file names; the submission program will not accept your submission if your file names differ at all from those specified.) From within that directory, type "submit hw5". This is not a partnership assignment; hand in your own work.

Part 1: sprint_float

In this first part you will be writing the C function:

void sprint_float (char *outbuf, uint64_t input, int exp_bits, int mant_bits)

The function should write to outbuf the string representation of input, interpreted as a float according to the parameters exp_bits and mant_bits. exp_bits refers to the number bits that should be used for the exponent field of the float, and mant_bits refers to the number of bits to be used for the mantissa of the float. There is also a single sign bit, so the total number of bits in the float (starting from the least significant bit) is 1 + exp_bits + mant_bits. Since the size of the exponent field may change, we must also adjust the built-in bias. This generalizes to -(2^(exp_bits-1)-1).

These parameters allow for a great deal of flexibility not only adjusting the expressive power of the float, but also the tradeoff between range and accuracy.


exp_bits = 4, mant_bits = 5
input: 0b----...--SEEEEMMMMM
- = Unused, S = Sign bit, E = Exponent, M = Mantissa (Significand)

Put your code in the framework in fp.c. Test code is provided in test.fp.c.  You can compile and execute your code under the test bench by typing "make fp".

Input specification:

Recall that uint64_t is the C99 64-bit int type.

You may assume that outbuf already has enough space allocated to hold your output. The quantity 1 + exp_bits + mant_bits will be some value <=64, with both exp_bits and mant_bits >=1 (i.e. there is always at least 1 exponent bit and 1 mantissa bit, and the total number of bits in the float, including the sign bit, will never exceed 64). Note that this implies that we could potentially deal with a float 3 bits wide, with one bit for each of S, E, and M. Such a float would not have any room to hold regular (normalized) float values!


Print it to outbuf according the format specified below:

The following table lists all the floating point possibilities ("maximal" refers to an exponent of all 1's):

Object Represented What you must write into the buffer
Exponent Mantissa
0 0 zero [-]0
0 nonzero ? denormalized number [-]denorm
nonzero, non-maximal anything ? normalized number [-]mantissa_in_binaryE[-]exponent_in_binary
according to rules above
maximal 0 ? infinity [-]infinity
maximal nonzero NaN (Not a Number) [-]NaN

Sample cases (make sure you understand each of these before you start coding!):

Value in input, exp_bits (e), mant_bits (m) What gets printed to buffer
(input in hex or binary)
0x fff0, e=5, m=10, -NaN
0x 6, e=2, m=1 infinity
0x 0000 0001 0000 0000, e=30, m=33 denorm
0b 11 0011, e=3, m=2 -11.1
0x 3455 4340, e=8, m=23 (standard float) 1.10101010100001101E-10111
0b 111 0110 1010, e=4, m=6 -1101010.0

Part 2: Float analysis

Now that we've familiarized ourselves with configurable float formats, we are ready to perform some basic analysis. In fp.c, complete the function:

int can_represent (int exp_bits, int mant_bits, int target)

The function should return 1 if the float specified by exp_bits and mant_bits can precisely represent the integer target, 0 otherwise.

Hint: Think about the binary representation of target

While we did not include test cases for this function in test.fp.c, it is strongly recommended that you add your own for debugging purposes.

Input Specifications

exp_bits and mant_bits will take on the same range of values as in part 1. target may be any signed integer.