Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
62d39de
Added homework 4
ilya-krivtsov Oct 5, 2024
2f431b8
Homework 4 task 1
ilya-krivtsov Oct 5, 2024
91966fd
Added homework 4 to root CMakeLists
ilya-krivtsov Oct 5, 2024
e954fd7
Merge branch 'hw-4' into hw-4-task-1
ilya-krivtsov Oct 5, 2024
5c86511
Merge branch 'build-system' into hw-4
ilya-krivtsov Oct 5, 2024
656b445
Merge branch 'hw-4' into hw-4-task-1
ilya-krivtsov Oct 5, 2024
6a58117
Changed bits from int8_t to bool
ilya-krivtsov Oct 16, 2024
b530bf8
Refactored ANSI printing
ilya-krivtsov Oct 16, 2024
4391cfb
Merge branch 'build-system' into hw-4-task-1
ilya-krivtsov Nov 7, 2024
57a37c6
Merge branch 'build-system' into hw-4-task-1
ilya-krivtsov Nov 7, 2024
47edc61
Merge branch 'main' into hw-4-task-1
ilya-krivtsov Nov 20, 2024
5e08122
Merge branch 'main' into hw-4-task-1
ilya-krivtsov Nov 23, 2024
97324a0
Merge branch 'main' into hw-4-task-1
ilya-krivtsov Nov 23, 2024
db4c4a8
Added parentheses (hw4 task 1)
ilya-krivtsov Nov 23, 2024
ead9cdd
Removed trailing whitespace (hw4 task 1)
ilya-krivtsov Nov 23, 2024
edf36fd
Merge branch 'main' into hw-4-task-1
ilya-krivtsov Nov 29, 2024
f92b82f
Fixed stdio.h include and added stdbool.h include (hw4 task 1)
ilya-krivtsov Dec 10, 2024
36124e3
Removed 'PRIVATE' dependency modifier (hw4 task 1)
ilya-krivtsov Dec 10, 2024
d82d99b
Replaced stdio.h includes with stdlib.h (hw4 task 1)
ilya-krivtsov Dec 10, 2024
ad90134
Merge branch 'main' into hw-4
ilya-krivtsov Dec 22, 2024
06487f2
Added README (hw 4)
ilya-krivtsov Dec 22, 2024
fdac254
Merge branch 'hw-4' into hw-4-task-1
ilya-krivtsov Dec 22, 2024
c329127
Added task name to README (hw4 task 1)
ilya-krivtsov Dec 22, 2024
fd5a0c3
Fixed task name (hw4 task 1)
ilya-krivtsov Dec 22, 2024
f67b920
Merge branch 'main' into hw-4-task-1
ilya-krivtsov Dec 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ add_compile_options(-Wall -Wextra)

add_subdirectory(homework_2)
add_subdirectory(homework_3)
add_subdirectory(homework_4)
5 changes: 5 additions & 0 deletions homework_4/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
project(homework_4)

set(homeworkName "${PROJECT_NAME}")

add_subdirectory(task_1)
3 changes: 3 additions & 0 deletions homework_4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Homework 4

[Task 1. Binary representation](/homework_4/task_1)
9 changes: 9 additions & 0 deletions homework_4/task_1/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
project("${homeworkName}_task_1")

add_library(binaryAddition binaryAddition.c)

add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} binaryAddition)

add_executable(${PROJECT_NAME}_test test.c)
target_link_libraries(${PROJECT_NAME}_test binaryAddition)
34 changes: 34 additions & 0 deletions homework_4/task_1/binaryAddition.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "binaryAddition.h"

#include <stdbool.h>
#include <stdlib.h>

int8_t addTwoNumbers(int8_t left, int8_t right, AdditionCallback callback) {
const int bitWidth = sizeof(int8_t) * 8;

int8_t result = 0;
int8_t accumulatedCarry = 0;
bool carryBit = 0;

if (callback != NULL) {
callback(left, right, result, accumulatedCarry, false, false, false, false, false, 0);
}

for (int i = 0; i < bitWidth; ++i) {
bool leftBit = ((left >> i) & 1) == 1;
bool rightBit = ((right >> i) & 1) == 1;
bool resultBit = ((leftBit + rightBit + carryBit) % 2) == 1;

bool newCarryBit = (leftBit + rightBit + carryBit) >= 2;

result |= resultBit << i;
accumulatedCarry |= newCarryBit << i;

if (callback != NULL) {
callback(left, right, result, accumulatedCarry, leftBit, rightBit, resultBit, carryBit, newCarryBit, i + 1);
}
carryBit = newCarryBit;
}

return result;
}
16 changes: 16 additions & 0 deletions homework_4/task_1/binaryAddition.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <stdbool.h>
#include <stdint.h>

/// Callback that is called after performing every step of addition.
/// Arguments in order: left, right, accumulatedResult, accumulatedCarryBits,
/// leftBit, rightBit, resultBit, oldCarryBit, newCarryBit, steps (0 before first step, incrementing after every step)
typedef void (*AdditionCallback)(int8_t, int8_t, int8_t, int8_t, bool, bool, bool, bool, bool, int);

/// @brief Adds two numbers with pre-step callback
/// @param left Left operand
/// @param right Right operand
/// @param callback Function to call after every step, can be `NULL`; it will be called once before first step
/// @return Result of the addition
int8_t addTwoNumbers(int8_t left, int8_t right, AdditionCallback callback);
153 changes: 153 additions & 0 deletions homework_4/task_1/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <locale.h>

#include "binaryAddition.h"

// set to false to disable color and line overrides
#define PRINT_ANSI true

#if PRINT_ANSI

#define ANSI_BG_YELLOW "\e[43m"
#define ANSI_FG_GREEN "\e[32m"
#define ANSI_RESET "\e[0m"

#else

#define ANSI_BG_YELLOW ""
#define ANSI_FG_GREEN ""
#define ANSI_RESET ""

#endif

void printBinary(int8_t number, int bits, int bitToHighlight) {
for (int i = bits - 1; i >= 0; --i) {
int bit = (number >> i) & 1;
if (i == bitToHighlight) {
printf(ANSI_FG_GREEN "%d" ANSI_RESET, bit);
} else {
printf("%d", bit);
}
}
}

void printStep(int8_t left, int8_t right, int8_t accumulatedResult, int8_t accumulatedCarry,
bool leftBit, bool rightBit, bool resultBit, bool oldCarryBit, bool newCarryBit, int steps) {

if (steps != 0) {
#if PRINT_ANSI
// 0th step prints 4 lines, 1st step and further - 6, and user inputs one more
const int clearLines = (steps == 1 ? 4 : 6) + 1;

// move cursor back, clear all lines and move cursor again
printf("\e[%dA", clearLines);
for (int i = 0; i < clearLines; ++i) {
printf("\e[K\n");
}
printf("\e[%dA", clearLines);
#endif
}

const int bitWidth = sizeof(int8_t) * 8;

// 1 space here because carry can overflow
printf(" ");
// print all carry bits
for (int i = bitWidth - 1; i >= 0; --i) {
if (((accumulatedCarry >> i) & 1) == 1) {
if (i + 1 == steps) {
printf(ANSI_BG_YELLOW "." ANSI_RESET);
} else {
printf(".");
}
} else {
printf(" ");
}
}
printf("\n");

// print left
printf(" ");
printBinary(left, bitWidth, steps - 1);
printf("\n");

// print right
printf("+ ");
printBinary(right, bitWidth, steps - 1);
printf("\n");

// print delimiter
printf(" ");
for (int i = 0; i < bitWidth; ++i) {
printf("-");
}
printf("\n");

if (steps > 0) {

const int stepsNotCompletedYet = bitWidth - steps;

// print result
printf("= ");
for (int i = 0; i < stepsNotCompletedYet; ++i) {
printf(" ");
}
printBinary(accumulatedResult, steps, steps - 1);
printf("\n");

// print head
printf(" ");
for (int i = 0; i < stepsNotCompletedYet; ++i) {
printf(" ");
}
printf("^ <--> %d + %d", leftBit, rightBit);

if (oldCarryBit != 0) {
printf(" + 1");
}

printf(" = %d", resultBit);

if (newCarryBit != 0) {
printf(" (1 в уме)");
}

printf("\n");
}

// wait for enter
while (getchar() != '\n') {}
}

int8_t readValue(const char *prompt, void (*printIncorrectValue)(long long, long long), long long lowLimit, long long highLimit) {
long long value;
printf("%s", prompt);
while ((scanf("%lld", &value) != 1) || value < lowLimit || value > highLimit) {
while (getchar() != '\n') {}
printIncorrectValue(lowLimit, highLimit);
}
return (int8_t)value;
}

void printError(long long lowLimit, long long highLimit) {
printf("введено неверное значение: число должно быть больше %lld и меньше %lld; попробуйте ещё раз: ", lowLimit, highLimit);
}

int main(void) {
setlocale(LC_ALL, "ru_RU.UTF-8");

int8_t left = readValue("введите первое число: ", printError, INT8_MIN, INT8_MAX);
int8_t right = readValue("введите второе число: ", printError, INT8_MIN, INT8_MAX);

// reset input
while (getchar() != '\n') {}

printf("для следующего шага нажмите Enter\n");

int8_t result = addTwoNumbers(left, right, printStep);

printf("результат: \n");
printf("%d + %d = %d\n", left, right, result);
}
41 changes: 41 additions & 0 deletions homework_4/task_1/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#define CTEST_MAIN
#define CTEST_SEGFAULT
#include "../../ctest/ctest.h"

#include <stdlib.h>

#include "binaryAddition.h"

int main(int argc, const char *argv[]) {
return ctest_main(argc, argv);
}

CTEST(additionTests, zeroTest) {
ASSERT_EQUAL(addTwoNumbers(0, 0, NULL), 0);
}

CTEST(additionTests, zeroPlusAnyTest) {
ASSERT_EQUAL(addTwoNumbers(0, 1, NULL), 1);
ASSERT_EQUAL(addTwoNumbers(0, 2, NULL), 2);
ASSERT_EQUAL(addTwoNumbers(0, 4, NULL), 4);
ASSERT_EQUAL(addTwoNumbers(0, 45, NULL), 45);
ASSERT_EQUAL(addTwoNumbers(0, 98, NULL), 98);
ASSERT_EQUAL(addTwoNumbers(0, 121, NULL), 121);
ASSERT_EQUAL(addTwoNumbers(0, -1, NULL), -1);
ASSERT_EQUAL(addTwoNumbers(0, -3, NULL), -3);
ASSERT_EQUAL(addTwoNumbers(0, -11, NULL), -11);
}

CTEST(additionTests, oneNegativeTest) {
ASSERT_EQUAL(addTwoNumbers(31, -29, NULL), 2);
ASSERT_EQUAL(addTwoNumbers(-16, 4, NULL), -12);
ASSERT_EQUAL(addTwoNumbers(-1, 1, NULL), 0);
ASSERT_EQUAL(addTwoNumbers(-100, 100, NULL), 0);
}

CTEST(additionTests, twoNegativeTest) {
ASSERT_EQUAL(addTwoNumbers(-31, -29, NULL), -60);
ASSERT_EQUAL(addTwoNumbers(-1, -2, NULL), -3);
ASSERT_EQUAL(addTwoNumbers(-10, -24, NULL), -34);
ASSERT_EQUAL(addTwoNumbers(-110, -10, NULL), -120);
}