- •Оглавление
- •Представление чисел в памяти эвм
- •Представление беззнаковых целых чисел в памяти эвм
- •Обратный код
- •Пример 1.
- •Пример 2.
- •Пример 3.
- •Пример 4.
- •Пример 5.
- •Пример 2.
- •Пример 3.
- •Пример 4.
- •Пример 5.
- •Важное следствие (пример 2).
- •Представление вещественных типов в памяти эвм
- •Пример 1
- •Пример 2
- •Пример 2
- •Пример 3
- •Пример 4
- •Алгоритмы работы с числами, которые представлены строкой
- •Сложение положительных чисел, представленных в виде строки
- •Реализация алгоритма на Pascal
- •Умножение положительного числа, представленного в виде строки, на одноразрядный коэффициент
- •Реализация алгоритма на Pascal
- •Умножение двух положительных целых чисел, представленных в виде строки
- •Реализация алгоритма на Pascal
- •Сравнение двух целых чисел, представленных в виде строки
- •Реализация алгоритма на Pascal
- •Вычитание целых чисел, представленных в виде строки
- •Реализация алгоритма на Pascal
- •Реализация алгоритмов работы с целыми числами, представленными в виде строки на c#
Реализация алгоритмов работы с целыми числами, представленными в виде строки на c#
Для сравнения приведем реализацию тех же самых алгоритмов на языке C# (версии 3.5)
class LongNumber {
private string num;
public LongNumber(string _num) {
Debug.Assert(_num != null);
num = _num;
}
public override string ToString() {
return num;
}
public static LongNumber operator +(LongNumber a, LongNumber b) {
var res = new LongNumber("");
var str1 = a.num;
var str2 = b.num;
str1 = str1.PadLeft(str2.Length, '0');
str2 = str2.PadLeft(str1.Length, '0');
var f = false;
for (var i = str1.Length - 1; i > -1; i--) {
var sum = Byte.Parse("" + str1[i]) + Byte.Parse("" + str2[i]);
if (f) {
sum++;
}
f = (sum > 9);
sum = sum % 10;
res.num = "" + sum + res.num;
}
if (f) {
res.num = "1" + res.num;
}
return res;
}
public static LongNumber operator *(LongNumber a, LongNumber b) {
var res = new LongNumber("0");
int offset = 0;
for (int i = b.num.Length - 1; i > -1; i--) {
var tempMul = new LongNumber(a.num);
var curVal = Int32.Parse("" + b.num[i]);
tempMul = tempMul*curVal;
for (int k = 0; k < offset; k++) {
tempMul.num = tempMul.num + "0";
}
offset++;
res = res + tempMul;
}
res.num = res.num.TrimStart('0');
if (res.num == "") {
res.num = "0";
}
return res;
}
public static LongNumber operator -(LongNumber a, LongNumber b) {
var s1 = a.num;
var s2 = b.num;
s1 = s1.PadLeft(s2.Length, '0');
s2 = s2.PadLeft(s1.Length, '0');
var res = "";
var f = false;
for (int i=s1.Length - 1;i>-1;i--) {
var n1 = Int32.Parse("" + s1[i]);
var n2 = Int32.Parse("" + s2[i]);
if (f) {
n1--;
}
var r = n1 - n2;
f = (r < 0);
if (f) {
r += 10;
}
res = "" + r + res;
}
res = res.TrimStart('0');
if (res == "") {
res = "0";
}
if (f) {
var tempStr = new String('0', res.Length);
tempStr = "1" + tempStr;
var l1 = new LongNumber(tempStr);
var l2 = new LongNumber(res);
res = (l1 - l2).num;
res = "-" + res;
}
return new LongNumber(res);
}
public int compare(LongNumber a) {
if (this.num.Length > a.num.Length) {
return 1;
}
if (this.num.Length < a.num.Length) {
return -1;
}
for (int i = 0; i < this.num.Length; i++) {
if (this.num[i] == a.num[i]) {
continue;
}
if (this.num[i] > a.num[i]) {
return 1;
}
return -1;
}
return 0;
}
public static LongNumber operator *(LongNumber a, int k) {
Debug.Assert(k > -1);
Debug.Assert(k < 10);
var res = new LongNumber("");
int f = 0;
for (int i = a.num.Length - 1; i > -1; i--) {
var sum = Int32.Parse("" + a.num[i]);
sum *= k;
sum += f;
f = sum / 10;
sum = sum % 10;
res.num = "" + sum + res.num;
}
if (f > 0) {
res.num = "" + f + res.num;
}
res.num = res.num.TrimStart('0');
if (res.num == "") {
res.num = "0";
}
return res;
}
}
Реализация алгоритмов работы с целыми числами, представленными в виде строки на C++
Для увеличения читабельности кода напишем небольшой вспомогательный класс для работы со строками.
Для удобства реализации создан специальный класс CppString, который облегчает работу с динамической строкой.
Полный код реализации приведен ниже:
#pragma once
#include <assert.h>
class CppString {
public:
~CppString() {
if (data != NULL) {
delete data;
}
}
CppString() {
data = new char[1];
data[0] = 0;
}
int length() {
return strlen(data);
}
CppString(char *_data) {
int size = strlen(_data);
data = new char[size + 1];
memmove(data, _data, sizeof(char) * size + 1);
}
CppString(const CppString &_data) {
int size = strlen(_data.data);
data = new char[size + 1];
memmove(data, _data.data, sizeof(char) * size + 1);
}
void addCharToEnd(char newC) {
int oldSize = strlen(data);
char *newData = new char[oldSize + 2];
memmove(newData, data, oldSize * sizeof(char));
newData[oldSize] = newC;
newData[oldSize + 1] = 0;
if (data != NULL) {
delete data;
}
data = newData;
}
char getChar(int index) {
assert(data != NULL);
assert(index > -1);
assert(index < strlen(data));
return data[index];
}
void print() {
if (data == NULL) {
printf("%s\n", "String is empty");
} else {
printf("%s\n", data);
}
}
void delCharFromStart() {
int oldSize = strlen(data);
char *newData = new char[oldSize ];
memmove(newData, &data[1], oldSize * sizeof(char));
if (data != NULL) {
delete data;
}
data = newData;
}
void addCharToStart(char newC) {
int oldSize = strlen(data);
char *newData = new char[oldSize + 2];
memmove(&newData[1], data, oldSize * sizeof(char));
newData[0] = newC;
newData[oldSize + 1] = 0;
if (data != NULL) {
delete data;
}
data = newData;
}
CppString operator + (const char &newChar) {
CppString res = CppString(*this);
res.addCharToEnd(newChar);
return CppString(res);
}
friend CppString operator + (const char &newCgar, const CppString &right);
CppString operator + (const CppString &left) {
CppString res;
int sizeRight = strlen(data);
int sizeLeft = strlen(left.data);
int sumSize = sizeLeft + sizeRight + 1;
res.data = new char[sumSize];
memmove(res.data, data, sizeof(char) * sizeRight);
memmove(&res.data[sizeRight], left.data, sizeof(char) * sizeLeft);
res.data[sizeLeft + sizeRight] = 0;
return CppString(res.data);
}
CppString operator = (const CppString &left) {
if (this == &left) {
return *this;
}
if (data != NULL) {
delete data;
}
int size = strlen(left.data) + 1;
data = new char[size];
memmove(data, left.data, size * sizeof(char));
return *this;
}
private:
char *data;
};
class NumberWorker {
public:
static CppString getSum(const CppString &right, const CppString &left) {
CppString a = right;
CppString b = left;
while (a.length() < b.length()) {
a = '0' + a;
}
while (b.length() < a.length()) {
b = '0' + b;
}
CppString res;
bool f = false;
for (int i = a.length() - 1; i > -1; i--) {
char ca = a.getChar(i) - '0';
char cb = b.getChar(i) - '0';
char c = ca + cb;
if (f) {
c++;
}
f = (c > 9);
if (c > 9) {
c -= 10;
}
res = (c + '0') + res;
}
if (f) {
res = '1' + res;
}
return CppString(res);
}
static int compare(CppString &right, CppString &left) {
if (right.length() > left.length()) {
return 1;
}
if (right.length() < left.length()) {
return -1;
}
for (int i = 0; i < right.length(); i++) {
if (right.getChar(i) == left.getChar(i)) {
continue;
}
return (right.getChar(i) - left.getChar(i));
}
return 0;
}
static CppString getMul(CppString &right, int k) {
char f = 0;
CppString res;
for (int i = right.length() - 1; i > -1; i--) {
char curVal = right.getChar(i) - '0';
curVal *= k;
curVal += f;
f = (curVal / 10);
curVal = curVal % 10;
res = (curVal + '0') + res;
}
if (f != 0) {
res = (f + '0') + res;
}
return CppString(res);
}
static CppString getMul(CppString &right, CppString &left) {
CppString res;
int offset = 0;
for (int i = left.length() - 1; i > -1; i--) {
char curChar = left.getChar(i) - '0';
CppString curMul = getMul(right, curChar);
for (int i = 0; i < offset; i++) {
curMul = curMul + '0';
}
offset++;
res = getSum(res, curMul);
}
return CppString(res);
}
static CppString getSub(const CppString &right, const CppString &left) {
CppString s1 = right;
CppString s2 = left;
while (s1.length() < s2.length()) {
s1 = '0' + s1;
}
while (s2.length() < s1.length()) {
s2 = '0' + s2;
}
CppString res;
bool flag = false;
for (int i = s1.length() - 1; i > -1; i--) {
char n1 = s1.getChar(i) - '0';
char n2 = s2.getChar(i) - '0';
if (flag) {
n1--;
}
char r = n1 - n2;
flag = (r < 0);
if (flag) {
r = r + 10;
}
res = (r + '0') + res;
}
while ((res.length() > 1) && (res.getChar(0) == '0')) {
res.delCharFromStart();
}
if (flag) {
CppString tempStr("1");
while (tempStr.length() <= res.length()) {
tempStr = tempStr + '0';
}
res = getSub(tempStr, res);
res = '-' + res;
}
return CppString(res);
}
};
CppString operator + (const char &newChar, const CppString &right) {
CppString res(right);
res.addCharToStart(newChar);
return CppString(res);
}
1 Порядок от младшего к старшему принят в памяти персональных компьютеров с x86-процессорами, в связи с чем, иногда, его называют интеловский порядок байтов (по названию фирмы-создателя архитектуры x86).
2 Этот порядок является стандартным для протоколов TCP/IP, он используется в заголовках пакетов данных и во многих протоколах более высокого уровня, разработанных для использования поверх TCP/IP. Поэтому, порядок байтов от старшего к младшему часто называют сетевым порядком байтов (англ. network byte order). Этот порядок байтов используется процессорами IBM 360/370/390, Motorola 68000, SPARC (отсюда третье название — порядок байтов Motorola, Motorola byte order)