public class Paranja1
{
uint _a;
uint _b;
public int A
{
get
{
return (int)_a;
}
set
{
_a = (uint)value;
}
}
public int B
{
get
{
return (int)_b;
}
set
{
_b = (uint)value;
}
}
public void Add()
{
_a += _b;
}
public void Sub()
{
_a -= _b;
}
public void Mul()
{
_a *= _b;
}
public void Div()
{
_a *= _b;
}
public void Left()
{
_a = _a << (int)_b;
}
public void Right()
{
_a = _a >> (int)_b;
}
}
public class Paranja2
{
public int A
{
get;
set;
}
public int B
{
get;
set;
}
public void Add()
{
A += B;
}
public void Sub()
{
A -= B;
}
public void Mul()
{
A *= B;
}
public void Div()
{
A *= B;
}
public void Left()
{
A = A << (int)B;
}
public void Right()
{
A = A >> (int)B;
}
}
Как теперь определить какой тип имеют закрытые поля?
Re: [этюд (обновление)] int uint -- что там внутри
Поясняю зачем это нужно. В языке Java вообще нет беззнаковых типов. И они без них живут, обходятся -- даже не думают о том что они так уж нужны. Код выше доказывает, что результат операции очень слабо зависит от того, имеет ли число знак.
Но все-же есть одна (как минимум одна, больше пока не нашел) тонкость, о которой знают либо очень дотошные люди (которые, видимо, понимают все тонкости работы процессора) либо кто столкнулся на практике. К примеру программисты MainSoft, которые сделали переводчик Grasshopper MSIL->Java об этом не знают и их переводчик падает на этой фишке.
Re: [этюд (обновление)] int uint -- что там внутри
0K>public class Paranja1
0K>{
0K> uint _a;
0K> uint _b;
0K> .....
0K>}
0K>public class Paranja2
0K>{
0K> public int A
0K> {
0K> get;
0K> set;
0K> }
0K> public int B
0K> {
0K> get;
0K> set;
0K> }
0K> .......
0K>}
0K>
0K>Как теперь определить какой тип имеют закрытые поля?
Способы:
1. Самый наипростейший — посмотреть исходник
2. Воспользоваться сдвигом вправо с отрицательным A. При этом беззнаковое будет заполняться слева нулями, а знаковое еденицами. Пример:
3. Насколько я помню из универа, двоичные операции умножения и деления знаковых и беззнаковых чисел отличаются. То есть можно найти в инете алгоритм умножения скажем беззнаковых чисел с помощью операций сложения и сдвига, реализовать его с помощь методов класса, а потом сравнить с результатом выполнения метода Mul. Но это я не проверял.
ICQ: 326084932
Re[2]: [этюд (обновление)] int uint -- что там внутри
Здравствуйте, Niswn, Вы писали:
N>1. Самый наипростейший — посмотреть исходник
Ну это не серьезно. Рефлексия и реверс запрещены (это в первый раз оговорил).
N>2. Воспользоваться сдвигом вправо с отрицательным A. При этом беззнаковое будет заполняться слева нулями, а знаковое еденицами. Пример:
Вот! Вы знали об этом, или только что проверили?
N>3. Насколько я помню из универа, двоичные операции умножения и деления знаковых и беззнаковых чисел отличаются. То есть можно найти в инете алгоритм умножения скажем беззнаковых чисел с помощью операций сложения и сдвига, реализовать его с помощь методов класса, а потом сравнить с результатом выполнения метода Mul. Но это я не проверял.
Кто знает подробнее?
Re[2]: [этюд (обновление)] int uint -- что там внутри
Здравствуйте, Niswn, Вы писали:
N>3. Насколько я помню из универа, двоичные операции умножения и деления знаковых и беззнаковых чисел отличаются. То есть можно найти в инете алгоритм умножения скажем беззнаковых чисел с помощью операций сложения и сдвига, реализовать его с помощь методов класса, а потом сравнить с результатом выполнения метода Mul. Но это я не проверял.
Т.е. Mul и Div у обеих паранджей отличаться не будут? Будут только двоичные деления отличаться?
Тогда можно проще -- найти эту двоичную операции, после которой результат Parandja1 и Parandja2 будет отличаться. Скорее всего это и будет сдвиг.
И вопрос ко всем. Кроме сдвига есть еще какие-нибудь операции, дающие разный результат? Можно использовать все существующие операции с целыми числами: +-*/|&^~
Re[3]: [этюд (обновление)] int uint -- что там внутри
Здравствуйте, 0K, Вы писали:
0K>Здравствуйте, Niswn, Вы писали:
N>>2. Воспользоваться сдвигом вправо с отрицательным A. При этом беззнаковое будет заполняться слева нулями, а знаковое еденицами. Пример:
0K>Вот! Вы знали об этом, или только что проверили?
Знал. Скорее даже не знал, а помнил с университетского курса. Это ж двоичная арифметика. Ну перед тем как запостить ответ конечно же проверил, а то вдруг процессоры теперь по другому считают.
N>>3. Насколько я помню из универа, двоичные операции умножения и деления знаковых и беззнаковых чисел отличаются. То есть можно найти в инете алгоритм умножения скажем беззнаковых чисел с помощью операций сложения и сдвига, реализовать его с помощь методов класса, а потом сравнить с результатом выполнения метода Mul. Но это я не проверял.
0K>Кто знает подробнее?
Если в гугле поискать, то там описываются алгоритмы для умножения двоичных чисел с помощью операций сложения+сдвиг. Но поскольку сдвиг и так однозначно показывает различие, то этот вариант я скорее привел для галочки.
Кстати было у меня ещё такое предположение:
В классе с uint имеется доп. операция приведения типов. И я думал, что если в цикле 10000000 раз проинициализировать и прочитать содержимое свойств, то для разных классов будет разное время выполнения (для uint по идеи должно быть больше). Но на практике время почти не отличается. То есть эта операция приведения ничего не стоит получается.
ICQ: 326084932
Re[3]: [этюд (обновление)] int uint -- что там внутри
Здравствуйте, 0K, Вы писали:
0K>Здравствуйте, Niswn, Вы писали:
N>>3. Насколько я помню из универа, двоичные операции умножения и деления знаковых и беззнаковых чисел отличаются. То есть можно найти в инете алгоритм умножения скажем беззнаковых чисел с помощью операций сложения и сдвига, реализовать его с помощь методов класса, а потом сравнить с результатом выполнения метода Mul. Но это я не проверял.
0K>Т.е. Mul и Div у обеих паранджей отличаться не будут? Будут только двоичные деления отличаться?
Конечно не будут.
Скорее всего будет отличаться только, если вы реализуете алгоритм умножения для беззнакового с помощью функций сложения/сдвига, а число окажется знаковым. Тогда вы просто получите неверный результат умножения. Ну я так предполагаю. Проверять времени нету.
0K>Тогда можно проще -- найти эту двоичную операции, после которой результат Parandja1 и Parandja2 будет отличаться. Скорее всего это и будет сдвиг.
Проще, но вы ж хотели все решения .
0K>И вопрос ко всем. Кроме сдвига есть еще какие-нибудь операции, дающие разный результат? Можно использовать все существующие операции с целыми числами: +-*/|&^~
Битовый операций кроме сдвига точно не дают различий. Операции сложения и вычитания тоже одинаковы для беззнаковых и знаковых чисел. Остается умножение/деление
ICQ: 326084932
Re[4]: [этюд (обновление)] int uint -- что там внутри
Здравствуйте, Niswn, Вы писали:
0K>>И вопрос ко всем. Кроме сдвига есть еще какие-нибудь операции, дающие разный результат? Можно использовать все существующие операции с целыми числами: +-*/|&^~ N>Битовый операций кроме сдвига точно не дают различий. Операции сложения и вычитания тоже одинаковы для беззнаковых и знаковых чисел. Остается умножение/деление
Можно попробовать устроить signed overflow (max_signed_int + 1) и посмотреть:
Чтобы арифметические операции, операции приведения или преобразования вызывали OverflowException, операция должна проходить в проверяемом контексте.По умолчанию проверка арифметических операций и переполнения ведется только в Visual Basic; в C# они не проверяются по умолчанию. Если операция выполняется в непроверяемом контексте, результат усекается путем удаления старших разрядов, которые не помещаются в целевой тип данных. http://msdn.microsoft.com/ru-ru/library/system.overflowexception.aspx
Когда я был молодым, высоким, кудрявым и красивым, а компьютеры были большими, единственным микропроцессором была реинкарнация i8080, гордо именовавшая себя 580ВМ80, и тогда каждый прогер должен был как "Отче наш" знать, что такое двоичное представление целого, дополнение до единицы, и какие бывают форматы представления чисел с плавающей запятой. Ну это было как-бы в базисе... А Вам оно зачем понадобилось?
Здравствуйте, Jolly Roger, Вы писали:
JR>Когда я был молодым, высоким, кудрявым и красивым, а компьютеры были большими, единственным микропроцессором была реинкарнация i8080, гордо именовавшая себя 580ВМ80, и тогда каждый прогер должен был как "Отче наш" знать, что такое двоичное представление целого, дополнение до единицы, и какие бывают форматы представления чисел с плавающей запятой. Ну это было как-бы в базисе...
Имхо, это и сейчас должно быть в базисе. Хотя бы как представлено число и как работают операции сдвига -- знать нужно всем.
JR>А Вам оно зачем понадобилось?
Начал проверять программу Grasshopper (автоматический перевод MS IL -> Java). Т.к. в Java нет беззнаковых чесел -- там такой баг есть со сдвигами. Их программисты об этом просто не подумали за несколько лет создания программы.