Commit 5035108b authored by kjc015's avatar kjc015
Browse files

Lab 08, Complete

parent 6bd35806
/*
* CSCI 206 Computer Organization & Programming
* Author: Alan Marchiori
* Date: 2014-03-01
* Updated for C: 2020-03-24
* Copyright (c) 2014 Bucknell University
*
* Permission is hereby granted, free of charge, to any individual or
* institution obtaining a copy of this software and associated
* on files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright and
* permission notice is maintained, intact, in all copies and supporting
* documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
float one_half_single(void){
/*
This function creates and returns a float with the value 0.5
You cannot just "return 0.5;"!
The 32-bit value 0x3f000000 is the value of 0.5 in IEEE 754.
If we use an array to access the bytes, wwe have to return
it in reverse order. Since the array is stored in little-endian
byte order, the most significant bits of the float are in index [3]!
+-------+-------+-------+-------+
| [0] | [1] | [2] | [3] | Memory byte offset
+-------+-------+-------+-------+
| 7-0 | 15-8 | 23-16 | 31-24 | Bits (IEEE single)
+-------+-------+-------+-------+
*/
unsigned char val[4] = {0, 0, 0, 0x3f};
return *(float*)val;
}
double one_half_double(void){
/*
Use an approach similar to one_half_single but now return
the double precision IEEE 754 value for 0.5 (8 byte).
*/
unsigned char val[8] = {0, 0, 0, 0, 0, 0, 0xe0, 0x3f};
return *(double*)val;
}
int main()
{
printf ("0.5 (single) = %f\n", one_half_single());
printf ("0.5 (double) = %lf\n", one_half_double());
return 0;
}
/*
* CSCI 206 Computer Organization & Programming
* Author: Alan Marchiori
* Date: 2014-03-01
* Updated for C: 2020-03-24
* Copyright (c) 2014 Bucknell University
*
* Permission is hereby granted, free of charge, to any individual or
* institution obtaining a copy of this software and associated
* on files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright and
* permission notice is maintained, intact, in all copies and supporting
* documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
float one_half_single(void){
/*
This function creates and returns a float with the value 0.5
You cannot just "return 0.5;"!
The 32-bit value 0x3f000000 is the value of 0.5 in IEEE 754.
If we use an array to access the bytes, wwe have to return
it in reverse order. Since the array is stored in little-endian
byte order, the most significant bits of the float are in index [3]!
+-------+-------+-------+-------+
| [0] | [1] | [2] | [3] | Memory byte offset
+-------+-------+-------+-------+
| 7-0 | 15-8 | 23-16 | 31-24 | Bits (IEEE single)
+-------+-------+-------+-------+
*/
unsigned char val[4] = {0, 0, 0, 0x3f};
return *(float*)val;
}
double one_half_double(void){
/*
Use an approach similar to one_half_single but now return
the double precision IEEE 754 value for 0.5 (8 byte).
*/
unsigned char val[8] = {0, 0, 0, 0, 0, 0, 0xe0, 0x3f};
return *(double*)val;
}
unsigned f2u(float f){
union {
unsigned u;
float f;
} v;
v.f = f;
return v.u;
}
unsigned long long d2u(double f){
union {
unsigned long long u;
double d;
} v;
v.d = f;
return v.u;
}
float u2f(unsigned d){
union {
unsigned u;
float f;
} v;
v.u = d;
return v.f;
}
double u2d(unsigned d){
union {
unsigned long long u;
double f;
} v;
v.u = d;
return v.f;
}
void inspect_float(float num){
unsigned u = f2u(num);
unsigned int* ptr = (unsigned int*)&u;
int sign = *ptr >> 31;
int e = *ptr & 0x7f800000;
e >>= 23;
int m = *ptr & 0x007fffff;
printf("Inspecting single %f, sign = %d, biased exponent = 0x%x, fraction = 0x%06x\n", num, sign, e, m);
}
void inspect_double(double num){
unsigned long long sign, exp, frac;
unsigned long long arg = d2u(num);
sign = arg >> 63;
exp = (arg << 1) >> 53;
frac = (arg << 12) >> 12;
printf("Inspecting double %f, sign = %lld, biased exponent = 0x%llx, fraction = 0x%013llx\n", num, sign, exp, frac);
}
int main()
{
printf ("0.5 (single) = %f\n", one_half_single());
inspect_float(one_half_single());
inspect_float(0.75);
inspect_float(0.875);
inspect_float(0.2);
printf ("0.5 (double) = %lf\n", one_half_double());
inspect_double(one_half_single());
inspect_double(0.75);
inspect_double(0.875);
inspect_double(0.2);
return 0;
}
/*
* CSCI 206 Computer Organization & Programming
* Author: Alan Marchiori
* Date: 2014-03-01
* Updated for C: 2020-03-24
* Copyright (c) 2014 Bucknell University
*
* Permission is hereby granted, free of charge, to any individual or
* institution obtaining a copy of this software and associated
* on files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright and
* permission notice is maintained, intact, in all copies and supporting
* documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
float one_half_single(void){
/*
This function creates and returns a float with the value 0.5
You cannot just "return 0.5;"!
The 32-bit value 0x3f000000 is the value of 0.5 in IEEE 754.
If we use an array to access the bytes, wwe have to return
it in reverse order. Since the array is stored in little-endian
byte order, the most significant bits of the float are in index [3]!
+-------+-------+-------+-------+
| [0] | [1] | [2] | [3] | Memory byte offset
+-------+-------+-------+-------+
| 7-0 | 15-8 | 23-16 | 31-24 | Bits (IEEE single)
+-------+-------+-------+-------+
*/
unsigned char val[4] = {0, 0, 0, 0x3f};
return *(float*)val;
}
double one_half_double(void){
/*
Use an approach similar to one_half_single but now return
the double precision IEEE 754 value for 0.5 (8 byte).
*/
unsigned char val[8] = {0, 0, 0, 0, 0, 0, 0xe0, 0x3f};
return *(double*)val;
}
unsigned f2u(float f){
union {
unsigned u;
float f;
} v;
v.f = f;
return v.u;
}
unsigned long long d2u(double f){
union {
unsigned long long u;
double d;
} v;
v.d = f;
return v.u;
}
float u2f(unsigned d){
union {
unsigned u;
float f;
} v;
v.u = d;
return v.f;
}
double u2d(unsigned d){
union {
unsigned long long u;
double f;
} v;
v.u = d;
return v.f;
}
void inspect_float(float num){
unsigned u = f2u(num);
unsigned int* ptr = (unsigned int*)&u;
int sign = *ptr >> 31;
int e = *ptr & 0x7f800000;
e >>= 23;
int m = *ptr & 0x007fffff;
printf("Inspecting single %f, sign = %d, biased exponent = 0x%x, fraction = 0x%06x\n", num, sign, e, m);
}
void inspect_double(double num){
unsigned long long sign, exp, frac;
unsigned long long arg = d2u(num);
sign = arg >> 63;
exp = (arg << 1) >> 53;
frac = (arg << 12) >> 12;
printf("Inspecting double %f, sign = %lld, biased exponent = 0x%llx, fraction = 0x%013llx\n", num, sign, exp, frac);
}
float next_float(float num){
return u2f(f2u(num) + 1);
}
int main()
{
float f = 7.8e9;
inspect_float(f);
printf("next_float(%1.23f) == %1.23f\n",
f,
next_float(f));
inspect_float(next_float(f));
return 0;
}
/*
* CSCI 206 Computer Organization & Programming
* Author: Alan Marchiori
* Date: 2014-03-01
* Updated for C: 2020-03-24
* Copyright (c) 2014 Bucknell University
*
* Permission is hereby granted, free of charge, to any individual or
* institution obtaining a copy of this software and associated
* on files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright and
* permission notice is maintained, intact, in all copies and supporting
* documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
const float EPS = 0.00000001;
float one_half_single(void){
/*
This function creates and returns a float with the value 0.5
You cannot just "return 0.5;"!
The 32-bit value 0x3f000000 is the value of 0.5 in IEEE 754.
If we use an array to access the bytes, wwe have to return
it in reverse order. Since the array is stored in little-endian
byte order, the most significant bits of the float are in index [3]!
+-------+-------+-------+-------+
| [0] | [1] | [2] | [3] | Memory byte offset
+-------+-------+-------+-------+
| 7-0 | 15-8 | 23-16 | 31-24 | Bits (IEEE single)
+-------+-------+-------+-------+
*/
unsigned char val[4] = {0, 0, 0, 0x3f};
return *(float*)val;
}
double one_half_double(void){
/*
Use an approach similar to one_half_single but now return
the double precision IEEE 754 value for 0.5 (8 byte).
*/
unsigned char val[8] = {0, 0, 0, 0, 0, 0, 0xe0, 0x3f};
return *(double*)val;
}
unsigned f2u(float f){
union {
unsigned u;
float f;
} v;
v.f = f;
return v.u;
}
unsigned long long d2u(double f){
union {
unsigned long long u;
double d;
} v;
v.d = f;
return v.u;
}
float u2f(unsigned d){
union {
unsigned u;
float f;
} v;
v.u = d;
return v.f;
}
double u2d(unsigned d){
union {
unsigned long long u;
double f;
} v;
v.u = d;
return v.f;
}
void inspect_float(float num){
unsigned u = f2u(num);
unsigned int* ptr = (unsigned int*)&u;
int sign = *ptr >> 31;
int e = *ptr & 0x7f800000;
e >>= 23;
int m = *ptr & 0x007fffff;
printf("Inspecting single %f, sign = %d, biased exponent = 0x%x, fraction = 0x%06x\n", num, sign, e, m);
}
void inspect_double(double num){
unsigned long long sign, exp, frac;
unsigned long long arg = d2u(num);
sign = arg >> 63;
exp = (arg << 1) >> 53;
frac = (arg << 12) >> 12;
printf("Inspecting double %f, sign = %lld, biased exponent = 0x%llx, fraction = 0x%013llx\n", num, sign, exp, frac);
}
float next_float(float num){
return u2f(f2u(num) + 1);
}
bool is_near(float num1, float num2, float epsilon){
if (fabs(num1) - num2 < epsilon){
return true;
}
return false;
}
int main()
{
float a = 0.1;
float sum = 0;
int i;
for (i = 0; i < 1000; i++)
{
sum += a;
}
printf ("a = %1.23f, sum = %1.23f, sum == 100 ==> %s\n",
a,
sum,
is_near(sum, 100, EPS)== 1 ? "TRUE":"FALSE");
inspect_float(a);
inspect_float(sum);
inspect_float(100-sum);
return 0;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment