Sie sind auf Seite 1von 18

10/3/2015

Lecture Outline
CS1010E Lecture 6
Computational Problem Solving and
Functional Abstraction
Semester 1 2015 / 2016

Need for abstraction


The Abstraction Ladder
Solving problems using abstraction ladder
Brief recipe
Pseudo-code Control + Functional abstraction
C Code

Further application of Functional abstraction

Need for abstraction


Example: Printing number 1 to 9 on the screen

Need for abstraction

C Code
#include <stdio.h>
int main(void){
int i;
for (i = 1; i <= 9; i++)
printf("%d ",i);
return 0;
}

10/3/2015

Need for abstraction

Need for abstraction

Example: Printing number 1 to 9 on the screen


Assembly Code

C Code

section
global _start
_start:

#include <stdio.h>
int main(void){
int i;

.text
;must be declared for using gcc
;tell linker entry point
mov ecx,10
mov eax, '1'

l1:

for (i=1; i<=9; i++)


printf("%d",i);
return 0;
}

section
num resb 1

mov [num], eax


mov eax, 4
mov ebx, 1
push ecx
mov ecx, num
mov edx, 1
int 0x80
mov eax, [num]
sub eax, '0'
inc eax
add eax, '0'
pop ecx
loop l1
mov eax,1
;system call number (sys_exit)
int 0x80
;call kernel
.bss

Binary code
1000100101001
1101010101010
0101001010101
0100101101011
1110101010010
1001001010010
1010010101010
0101001010010
1010101010010
1010010100101
1010101001010

C assembly language machine code


Abstract concrete
Difficult to work at this level

Control abstraction (selection/repetition


constructs)
Hides away unnecessary details
Makes it more intuitive to formulate solutions

Computational Problem Solving


The Abstraction Ladder
In problem solving there is an "abstraction ladder"
Brief recipe

Computational Problem Solving


The Abstraction Ladder

Pseudo-Code

C Code

10/3/2015

Computational Problem Solving


Going down The Abstraction Ladder
When solving a computational problem always
start from the most abstract (top of ladder) and
works towards the bottom (the C code)
Never jump straight into code !
Navigating the abstraction ladder is more an "art"
rather than science
There are however rules of thumb to help
Practice makes perfect !

Problem:
Write a C Program that
computes the taxi fare
from distance travelled and
prints it out.

Solving problems using abstraction ladder


NTUC Comfort, the largest taxi operator in
Singapore, determines the taxi fare based
on distance traveled as follows:
For the first kilometre or less:
Every 400 metres thereafter or less up to 10 km:
Every 350 metres thereafter or less after 10 km:

$3.40
$0.22
$0.22

Solving problems using abstraction ladder


Top Level Brief recipe
1. Get the distance travelled
2. Compute the taxi fare from the distance
travelled
3. Print out the taxi fare

Specify what is to be done

10/3/2015

Solving problems using abstraction ladder


Top Level Brief recipe
Step 1 and 3 are easy
Step 2 - Compute the taxi fare from the
distance travelled

This is more complicated,


how to do this?

Wishful thinking
Assume you already a function which
computes the taxi fare given distance travelled!
Give function meaningful name compTaxiFare
What is input required distance
What is output fare
This is functional abstraction

Functional Abstraction
Functional Abstraction

=
Black Box
No need to know how a car works to drive it!

Functional abstraction tells you the


specification rather than implementation
Specification:
Implementation:

WHAT
HOW

Delay the how by


transforming into a what

10/3/2015

Solving problems using abstraction ladder


Middle Level Pseudo Code

Solving problems using abstraction ladder


Middle Level Pseudo Code
The pseudo code is directly and easily
translatable to C code

1. Get the distance travelled


2. fare = compTaxiFare(distance)
3. Print out the taxi fare

Pseudo Code = Informal Code


English + Control structures +
Functional units

Solving problems using abstraction ladder


Bottom level C Code (the main function)

Determine input parameters and output type for


compTaxiFare prototype
distance in
meters
double compTaxiFare(int d);
Determine other variables required in main
function and their type
int d;
double fare;

#include <stdio.h>
double compTaxiFare(int d);

#include <stdio.h>
int main(void) {
int d;
double fare;

double compTaxiFare(int d);


int main(void) {
int d;
double fare;

If we assume compTaxiFare
is written then we already
have our program!
Step 1

printf("Enter dist: ");


scanf("%d",&d);
fare = compTaxiFare(d);
printf("Taxi fare = %f\n",fare);
return 0;
}

Step 2
Step 3

By writing a stub for


compTaxiFare, we can
compile the program and
check for syntax error.
Part of incremental program
development

printf("Enter dist: ");


scanf("%d",&d);
fare = compTaxiFare(d);
printf("Taxi fare = %f\n",fare);
return 0;
}
double compTaxiFare(int d) {
return 0.0;
}

Stub for compTaxiFare.


Basically a temporary
stand-in for its actual code.

10/3/2015

1.

Good Abstraction

Not the end !

Functional abstraction
separates specification
from implementation

Dont celebrate yet, we


havent finished!

Specification = What
Implementation = How

Still need to define


compTaxiFare

Not the end !

Not the end !

How to write compTaxiFare?

This is an iterative process,


repeat for each function you
need to write until entire
program is written

Start from top of ladder again


and repeat process if you think
its still too complicated!

10/3/2015

Computing taxi Fare


NTUC Comfort, the largest taxi operator in
Singapore, determines the taxi fare based on
distance traveled as follows:
For the first kilometre or less: $3.40
Every 400 metres thereafter or less up to 10 km:$0.22
$0.22 charged at 1001m, 1401m 9801m

Every 350 metres thereafter or less after 10 km: $0.22


$0.22 charged at 10001m, 10351m 12451m

Solving problems using abstraction ladder


Top Level Brief recipe
Basic recipe for compTaxiFare
1. fare is 3.40 if dist <= 1km
2. fare is X if 1km < dist <= 10km
3. fare is Y if dist > 10km
Complicated to
compute

Solving problems using abstraction ladder


Top Level Brief recipe
Basic recipe for compTaxiFare
1. fare is 3.40 if dist <= 1km
2. fare is X if 1km < dist <= 10km
3. fare is Y if dist > 10km
dist <= 1km

Stage1

1km < dist <= 10km

Stage2

dist > 10km

Stage3

Solving problems using abstraction ladder


Top Level Brief recipe
Wishing Thinking ! Assume we have the
functions to compute fare for distances
travelled up to stage 2 and up to stage 3
fareStage2: get fare given distance up to stage 2
fareStage3: get fare given distance up to stage 3

10/3/2015

Solving problems using abstraction ladder


Middle Level Pseudo Code

Solving problems using abstraction ladder


Bottom Level C Code

Basic recipe for compTaxiFare


1. fare = 3.40
if dist <= 1km
2. fare = fareStage2(dist) if 1km < dist <= 10km
3. fare = fareStage3(dist) if dist > 10km

double compTaxiFare(int d) {
double fare;
Yet again, if we assume fareStage2

and fareStage3 is written then we

if (d <= 1000)
already have our program!
fare = 3.40;
else if (1000 < d && d <= 10000)
fare = fareStage2(d);
else
fare = fareStage3(d);
return fare;
}

#include <stdio.h>
double computeTaxiFare(int d);
double fareStage2(int d);
double fareStage3(int d);
int main() {
int d;
double fare;
printf("Enter dist: ");
scanf("%d",&d);
fare = compTaxiFare(d);
printf("Taxi fare = %f\n",fare);
return 0;

Yet again we can write stubs


for fareStage2 and fareStage3
and compile the program

fareStage2 and fareStage3 should be


simple enough for us to try and
implement them now

double compTaxiFare(int d){


double fare;
if (d <= 1000)
fare = 3.40;
else if (1000 < d && d <= 10000)
fare = fareStage2(d);
else
fare = fareStage3(d);
return fare;
}
double fareStage2(int d) { return 0.0; }
double fareStage3(int d) { return 0.0; }

10/3/2015

Implementing fareStage2
Try out simple examples
Example distance = 3,300 m

Implementing fareStage2
Try out simple examples
Example distance = d

Generalize !

for 1st 1000m -> $3.40


at 1001m -> $0.22
remaining (3300-1001)m -> ((3300-1001)/400)*$0.22

for 1st 1000m -> $3.40


at 1001m -> $0.22
remaining (d-1001)m -> ((d-1001)/400)*$0.22

fare = $3.40 +
$0.22 +
(((3300-1001)/400)*$0.22)
= $4.72

fare = $3.40 +
$0.22 +
(((d-1001)/400)*$0.22)

fareStage2

Implementing fareStage3
Try out simple examples
Example distance = 14500 m

double fareStage2(int d) {
return 3.40+0.22+(((d-1001)/400)*0.22);
}

for 1st 1000m -> $3.40


for next 9000m -> $0.22 + (((9000-1001)/400)*$0.22)
at 10001m -> $0.22
remaining (14500-10001)m -> ((14500-10001)/350)*$0.22
fare = $3.40 +
$0.22 + (((9000-1001)/400)*$0.22) +
$0.22 + (((14500-10001)/350)*$0.22) = $11.76

10/3/2015

Implementing fareStage3
Try out simple examples
Example distance = d

Generalize !

Implementing fareStage3
Try out simple examples
Example distance = d

Calculated by fareStage2

for 1st 1000m -> $3.40


for next 9000m -> $0.22 + (((9000-1001)/400)*$0.22)
at 10001m -> $0.22
remaining (d-10001)m -> ((d-10001)/350)*$0.22

for 1st 1000m -> $3.40


for next 9000m -> $0.22 + (((9000-1001)/400)*$0.22)
at 10001m -> $0.22
remaining (d-10001)m -> ((d-10001)/350)*$0.22

fare = $3.40 +
$0.22 + (((9000-1001)/400)*$0.22) +
$0.22 + (((d-10001)/350)*$0.22)

fare = $3.40 +
$0.22 + (((9000-1001)/400)*$0.22) +
$0.22 + (((d-10001)/350)*$0.22)

Implementing fareStage3
Try out simple examples

fareStage3

Example distance = d
for 1st 10000m -> fareStage2(10000)
at 10001m -> $0.22
remaining (d-10001)m -> ((d-10001)/350)*$0.22

double fareStage3(int d) {
return fareStage2(10000)+
0.22+(((d-10001)/350)*0.22);
}

fare = fareStage2(10000)+
$0.22 + (((d-10001)/350)*$0.22)

10

10/3/2015

#include <stdio.h>
double computeTaxiFare(int d);
double fareStage2(int d);
double fareStage3(int d);
int main() {
int d;
double fare;
printf("Enter dist: ");
scanf("%d",&d);

fare = compTaxiFare(d);
printf("Taxi fare = %f\n",fare);
return 0;

Problem Solved !

Slightly long but very readable

double compTaxiFare(int d){


double fare;
if (d <= 1000)
fare = 3.40;
else if (1000 < d && d <= 10000)
fare = fareStage2(d);
else
fare = fareStage3(d);
return fare;
}
double fareStage2(int d){

return 3.40+0.22+(((d-1001)/400)*0.22);
}
double fareStage3(int d) {

return fareStage2(10000)+0.22+(((d-10001)/350)*0.22);
}

Good Abstraction

Good Abstraction

2. Make programs easier


to understand by hiding
irrelevant details

3. Makes it more natural to


think of a solution in
terms of tasks and
subtasks

Water molecule
represented as 3 balls

11

10/3/2015

Building a house
House

Bricks

Rooms

"Building" a program
Program

Primitives

Functions

Divide and
Conquer

Walls
Bricks

Primitives

Many different taxi companies !

What if want to compute


fare for different taxi
companies?

12

10/3/2015

Change in main function to


accommodate different taxi companies
Meter Fare

Normal

Limousine

Chrysler

Flag-Down
(inclusive of 1st km
or less)

$3.40

$3.90

$5.00

Every 400m
thereafter or less up
to 10km

$0.22

$0.22

$0.33

Every 350 metres


thereafter or less
after 10 km

$0.22

$0.22

$0.33

int main() {
int d,taxi;
double fare;
printf("Enter taxi company and dist: ");
scanf("%d%d",&taxi,&d);
Dont work anymore !
fare = compTaxiFare(d);
printf("Taxi fare = %f\n",fare);
return 0;
}
Read in taxi company 1 is normal, 2 is limousine, 3 is Chrysler

Avoid Magic Numbers

double compTaxiFare(int d){


double fare;

if (d <= 1000)
fare = 3.40;
else if (1000 < d && d <= 10000)
fare = fareStage2(d);
else
All the highlighted "magic
fare = fareStage3(d);
numbers" will not work across
return fare;
}

different taxi companies!

double fareStage2(int d){


return 3.40+0.22+(((d-1001)/400)*0.22);
}
double fareStage3(int d) {
return fareStage2(10000)+0.22+(((d-10001)/350)*0.22);
}

Avoid Magic Numbers


It is a terrible idea to hardcode
numbers (magic numbers):
Hard to make changes in future
Not general enough
Define abstractions to hide them!
Encode flag down fare and increment as function parameter

13

10/3/2015

Avoid Magic Numbers Encode as


function parameters
double computeTaxiFare(int d,
double flagdown, double incre);
double fareStage2(int d,
double flagdown, double incre);
double fareStage3(int d,
double flagdown, double incre);

Avoid Magic Numbers Encode as


function parameters
double compTaxiFare(int d, double flagdown, double incre){
double fare;

The input arguments


main function

if (d <= 1000)
passed in by
fare = flagdown;
else if (1000 < d && d <= 10000)
fare = fareStage2(d,flagdown,incre);
else
fare = fareStage3(d,flagdown,incre);
return fare;

}
double fareStage2(int d, double flagdown, double incre){
return flagdown+incre+(((d-1001)/400)*incre);
}
double fareStage3(int d, double flagdown, double incre) {
return fareStage2(10000,flagdown,incre)+incre+
(((d-10001)/350)*incre);
}

Avoid Magic Numbers Encode as


function parameters
int main() {
int d,taxi;
double fare;
printf("Enter taxi company and dist: ");
scanf("%d%d",&taxi,&d);
if (taxi == 1) /* normal cab */
fare = compTaxiFare(d,3.40,0.22);
else if (taxi == 2) /* limousine */
fare = compTaxiFare(d,3.90,0.22);
else /* Chrysler */
fare = compTaxiFare(d,5.0,0.33);
printf("Taxi fare = %f\n",fare);
return 0;

Coping with change


What if
1. Stage distance changes?
2. Distance per increment changes?

14

10/3/2015

Coping with change

Coping with change

double compTaxiFare(int d, double flagdown, double incre){


double fare;

The highlighted "magic

if (d <= 1000)
numbers" will not work
fare = flagdown;
else if (1000 < d && d <= 10000)
fare = fareStage2(d,flagdown,incre);
else
fare = fareStage3(d,flagdown,incre);
return fare;

Yet again define abstraction to hide them

!
Encode stage distances and distance per increment as
Constants !

}
double fareStage2(int d, double flagdown, double incre){
return flagdown+incre+(((d-1001)/400)*incre);
}
double fareStage3(int d, double flagdown, double incre) {
return fareStage2(10000,flagdown,incre)+incre+
(((d-10001)/350)*incre);
}

Avoid Magic Numbers 2nd way


constant definitions
#define
#define
#define
#define

STAGE1
STAGE2
BLOCK1
BLOCK2

1000
10000
400
350

Can be easily changed and the


changes will be reflected throughout
the code

Avoid Magic Numbers 2nd way


constant definitions
double compTaxiFare(int d, double flagdown, double incre){
double fare;
if (d <= STAGE1)
fare = flagdown;
else if (STAGE1 < d && d <= STAGE2)
fare = fareStage2(d,flagdown,incre);
else
fare = fareStage3(d,flagdown,incre);
return fare;
}
double fareStage2(int d, double flagdown, double incre){
return flagdown+incre+(((d-1-STAGE1)/BLOCK1)*incre);
}
double fareStage3(int d, double flagdown, double incre) {
return fareStage2(STAGE2,flagdown,incre)+incre+
(((d-1-STAGE2)/BLOCK2)*incre);
}

15

10/3/2015

Good Abstraction

4.

Allows code to be more


general and easily changed
to reflect changes in
problem definition

#include <stdio.h>
#define STAGE1 1000
#define STAGE2 10000
#define BLOCK1 400
#define BLOCK2 350
double compTaxiFare(int d, double flagdown, double incre);
double fareStage2(int d, double flagdown, double incre);
double fareStage3(int d, double flagdown, double incre);
int main() {
int d,taxi;
double fare;
printf("Enter taxi company and dist: ");
scanf("%d%d",&taxi,&d);
if (taxi == 1) /* normal cab */ {
printf("Here !\n");
fare = compTaxiFare(d,3.40,0.22);
}
else if (taxi == 2) /* limousine */
fare = compTaxiFare(d,3.90,0.22);
else /* Chrysler */
fare = compTaxiFare(d,5.0,0.33);
printf("Taxi fare = %f\n",fare);
return 0;
}

double compTaxiFare(int d, double flagdown, double incre){


double fare;
if (d <= STAGE1)
fare = flagdown;
else if (STAGE1 < d && d <= STAGE2)
fare = fareStage2(d,flagdown,incre);
else
fare = fareStage3(d,flagdown,incre);
return fare;
}

Good Abstraction

5.

Captures common patterns


& allow for code reuse

double fareStage2(int d, double flagdown, double incre){


return flagdown+incre+(((d-1-STAGE1)/BLOCK1)*incre);
}
double fareStage3(int d, double flagdown, double incre) {
return fareStage2(STAGE2,flagdown,incre)+incre+
(((d-1-STAGE2)/BLOCK2)*incre);
}

16

10/3/2015

Abstract out commonly performed


tasks as functions
Many different programs frequently have to
perform some routine tasks

Declare and Define the swap function


void swap(int *a, int *b);

Eg swapping the values of 2 variables

Such tasks can be abstracted out as a function


Calling the function to perform the task is much
simpler and less error prone

void swap(int *a, int *b) {


int temp;
temp = *a;
*a = *b;
*b = temp;

Example - Abstract out swapping the value of


2 integer variables as a function

return;
}

#include <stdio.h>

#include <stdio.h>

int main(void) {
int a,b,c,temp;

int main(void) {
int a,b,c;

Example program
that does swapping
without using the
swap function

scanf("%d%d%d",&a,&b,&c);

scanf("%d%d%d",&a,&b,&c);

/* swap a and b*/


temp = a;
a = b;
b = temp;

/* swap a and b*/


swap(&a,&b);

/* swap b and c*/


temp = b;
b = c;
c = temp;

Example program
after using the swap
function

/* swap b and c*/


swap(&b,&c);
/* swap c and a*/
swap(&c,&a);
return 0;

/* swap c and a*/


temp = c;
c = a;
a = temp;

return 0;
}

17

10/3/2015

Summary
Computational Problem solving using the
ladder of abstraction
Good abstraction
Separate specification from implementation
Makes code easier to read
Hides irrelevant detail
Allows code to be more general
Captures common patterns and allow for reuse
Makes it more natural to think of solution in terms
of task and subtasks

18

Das könnte Ihnen auch gefallen