Problem 12.Extract Bit from Integer HomeWork 3
Ето и малко помощ от мен относно тази задача.
http://pastebin.com/JAyW42vJ
Ако някой има друго рещение да сподели :)
Ето и малко помощ от мен относно тази задача.
http://pastebin.com/JAyW42vJ
Ако някой има друго рещение да сподели :)
Здравей ето и моето решение
Мен лично повече ме затруднява 14 задача от същото домашно, ако има предложения пишете :)
using System;
class extractBitFromInteger
{
static void Main()
{
Console.WriteLine("Give an integer: ");
int number = int.Parse(Console.ReadLine());
Console.WriteLine("Give a position of the bit you want to see ");
int position = int.Parse(Console.ReadLine());
int nRightP = number >> position;
int bit = nRightP & 1;
Console.WriteLine(bit);
}
}
using System;
namespace Homework3_Task12_bitP
{
class bitP
{
static void Main()
{
int bit = int.Parse(Console.ReadLine());
int p = int.Parse(Console.ReadLine());
string bitcheck = Convert.ToString(bit, 2);
Console.WriteLine(bitcheck.PadLeft(8, '0'));
Console.WriteLine("The #3 digit in right to left, witch is infact fourth, but anyway");
int text = 0;
for (int i = 0; i < bitcheck.Length; i++)
{
text++;
}
if (p < 256)
Console.WriteLine(bitcheck[text - (p+1)]);
}
}
}
Това не е с битови операции и не го препоръчвам. Изглежда вярно и ще работи, но ще отнеме много повече ресурси, отколкото ще имаш в реална ситуация. Например в Arduido нямаш стрингове. Просто нямаш! Някои микроконтролери имат памет 4KB. Там няма стрингове! Това ще работи на компютър и таблет, но няма да работи на повечето микроконтролери. Научи битовите операции!
Здравейте, аз също съм имал големи проблеми с този метод на преобразуване, веднъж ми обърка цялата задача ...
Битовите операции не са трудни, макар, че в началото и на мен ми се виждаха много тегави. Всичко е до опит.
Поздрави !
Ето и за 13. със true i false .
Използвам същтия цикъл от 12 задача .Само добавям true , false
Благодаря tinta, програмката сработи и най-важното схванах идеята от твото обяснение!
Поздрави
Има 2 начина да се "изтръгне" стойността на бит с побитови операции .
И за двата се използва даденото число и числото 1.
При единият, даденото число не се пипа, стои си на мястото , a местим числото 1 - наляво (<<) .
При другият , числото 1 не се пипа, стои си на мястото, а местим даденото число надясно (>>).
Когато местим нещо независимо числото ли е или единицата, местим на толкова позиции , колкото е номера на позицията на търсеният бит.
Хайде да намерим и по двата начина , какво има в бита на позиция 4 на числото 27 .
27 в бинарната бройна система е 00110011 (за 8 битово число, за 16 ,32 ,64 и тъй нататъка- битово, отпред има съответният брой нули, но те не ни интересуват !)
( Двойчното представяне го взимаме или от калкулатора на Уиндоус за програмисти или с командата ConvertToString(27,2)р но нас ни трябва само за визуализиране, компютъра сам си ги превръща от една в друга бройна система !
Позициите се броят от дясно на ляво, като се почва от 0
За нашият пример за 8 битово число , изглежда така:
Позиция : 7 6 5 4 3 2 1 0
Стойност на бита в позицията : 0 0 0 1 1 0 1 1
Двоичното представяне на единицата е 00000001.
Първи начин :
Ще местим числото , а няма да пипаме единицата!
110011 >> 11 ( местим 4 позии надясно и всъщност докарваме бита , стойността на който който търсим - най- в дясно.Отляво компютъра запълва автоматично с нули при операция >>
Сега умножаваме побитово двете числа (логическо умножение ), позиция по позиция , от дясно наляво:
00000011
&
00000001
)Сега умножаваме бит по бит , позиция по позия ,
Тъй като само 1 Х 1 дава 1 , само най-десният бит дава 1, останалите 0, каквото и да има в тях
Ако получим 1 (както в този случай ) в бита който търсим има 1
Ако получим 0 (0 Х 1 . 0 ) в бита има 0.
Това , което направихме , се записва така на с#:
int mask = number >> pos;
int bitValue = number & mask;
number = 27;
pos = 4;
mask = 000011011 >> 4 = 0000001;
bitValue = 00000001 & 00000001;
bitValue =1;
ВТОРИЯТ НАЧИН
Местим единицата 1 на ляво, за да достигнем с нея бита на търсената позиция - числото не мърда !
Същият пример:
27 , bit in position 4 = ?
1<<4 <= > 00000001 << 4 = 00010000
00011011
&
00010000
=
00010000 >> 4 <=> 00000001 = 1
Пак умножаваме бит по бит, позиция по позиция и понеже само под търсеният бит имаме единици , а всички останали са нули и умножението им дава или 0 Х 0 = 0 или 0 Х 1=0) - всички дават нули , а само нашият бит, в търсената позиция дава 1 Х 1 = 1.
Ако търсеният бит беше нула и това умножение щеше да е нула .
Сега остава , да върнем единицата (или ако е нула - нулата№ )обратно на нулева позиция , където ще даде или 1 (00000001) или 0 (00000000) или търсената стойност на нашият бит в 4 позиция.
Или това се записва така :
int mask = 1<< position;
int bitValue = (mask & number) >> position;
И тези 2 реда или горните два са цялото решение на задачата за извличане на бит от дадено число и позиция .
Пак ще ги запиша :
int number;
int pos;
int mask = number >> pos;
int bitValue = 1 & mask;
или
int number;
int pos;
int mask = 1<< position;
int bitValue = (mask & number) >> position;
И двата начина правят едно и също , изберете си който искате !
Добро обяснение, но с една малка забележка:
int mask = number >> pos;
int bitValue = number & mask;
Според мен горните два реда трябва да са
int mask = number >> pos;
int bitValue = 1 & mask;
Вторият начин е малко безмислен, защото в крайна сметка пак връщаме търсеният бит най-вдясно.
Правилно си забелязал , грешка е - оправих го
Ами то - цял ферман съм изписала - как да не сбъркаш някъде !
Благодаря за поправката и за изчитането на фермана ми !
Ами на мен ми е по-удобно и приятно да измествам 1 при позицията , но на някой може да му харесва повече, да мести номера (позицията) при единицата !
Нещо ,като :
"Когато Мохамед не отива при планината - планината отива при Мохамед"
Ето я 14 задача, после ще ви кажа , коло просто става замяната ня стойностите в битовете с побитовите операции - аз им хванах цаката , че отивам да правя вечеря !
using System;
class ModifyBitAtGivenPosition
{
static void Main()
{
Console.Write("Enter a number (Min value = 0, Max value = ");
Console.WriteLine(uint.MaxValue + "): \n");
uint number= uint.Parse( Console.ReadLine());
Console.WriteLine("\nEnter the bit position, the bit in it, you want to change (Min value = 0, Max value = 31): \n");
int p = int.Parse( Console.ReadLine());
Console.WriteLine("\nEnter the value you want to put in the bit at position " + p + " (0 or 1): \n");
int v = uint.Parse( Console.ReadLine());
uint oldNumber = number;
uint mask = 1u << p; //shifting 1 to position p
// let's get the bit value in p
uint bitP = (number & mask) >> p; // 1 or 0
if (v == 1)
{
// let's change the bit value in p from 0 to 1
number = number | mask;
}
else if (v == 0)
{
// let's change the bit value from 1 to 0
mask = ~mask;
number = number & mask;
}
Console.WriteLine("\n\nResult : \n\nOld bit value " + bitP + " ---> " + v + " New bit value \n\n"
+ "Old number " + oldNumber + " ---> " + number + " New number\n\n\n ");
}
}
В зависимост от това дали поставяме 0 или 1 , като нова стойност в бита има 2 метода.
Няма значение, каква стойност съдържа бита до момента - методите зависят само от това каква нова стойност поставяме - 1 или 0.
Всъшност, ако в бита се съдържа 0 и пак му поставим 0 или съдържа 1 и пак му поставим 1 - числото си остава едно и също ,но не е необходимо да проверяваме за еднаквост на новата и старата стойност, тъй като проверката е по сложна от самата операция на инсталиране на нова стойност , макар и да е същата.
Когато вкарваме 1 , на мястото на 0 , всъщност събираме числото с 2 на степен номера на позицията, в която вкарваме единица.
Когато вкарваме 0 на мястото 1, всъщност изваждаме от числото 2 на степен номера на позицията, в която вкарваме 0.
(по този начин също могат да се решат задачите с битове - с умножение и деление на 2**pos )
С побитови операции това става така :
Маската се намира по един и същ начин и при вкарване на 0 , и при вкарване на 1 :
mask = 1<< position;
1. Вкарване на 1 в бит на позиция position :
// change Bit Value to 1
number = number | mask;
Вкарване на 0 в бит на позиция position :
// change Bit Value to 0
mask= ~ mask;
number = number & mask ;
А, защо е така ?
Пример с 27 искаме да вкараме 1 на позиция 2 (третата позиция от дясно наляво)
27 = 00110011
mask = 1<<2 ( 00000001 <<2 = 00000100 )
Ползваме формулата за вкарване на 1 в бит:
number = number | mask;
number = 00110011 | 00000100 (логическо събиране )
00011011
|
00000100
=
0011111 , както се вижда , вече имаме 1 на 3-та позиция, а не 0.
Числото от 27 стана 31 .
27 + 2**position = 27 + 2**2 = 31
Сега да вкараме 0 ,да кажем на позиция 4, пак на 27 .
по формулата за вкарване на 0 в бит за дадено число на дадена позиция 4, имаме :
mask= ~ mask;
number = number & mask ;
Маската се намира по същият начин - с местене на двоичното число 1 на ляво ,до зададената позиция :
mask = 1 << 4; (00000001 << 4 = 00010000)
Заместваме във формулата :
mask = ~ mask ; ( ~ 00010000 = 11101111) - логическо отрицание, обръща всяка 0 в 1 и всяка 1 в 0
number = number & mask ; ( 00011011 & 11101111)
00011011
&
11101111
=
00001011 ( = 11 in decimal )
Или числото 27 стана 11.
27 - 2**position = 27 - 2**4 = 27 -16 = 11
Ето го и моето решение на 12 задача :)
using System;
class Bits
{
static void Main()
{
Console.WriteLine("Enter number: ");
int n = int.Parse(Console.ReadLine());
Console.WriteLine("Enter position: ");
int p = int.Parse(Console.ReadLine());
int mask = (1 << p) & n;
int mask2 = mask >> p;
Console.WriteLine(mask2);
}
}
Problem 9.Bit Destroyer (Write a program that sets the bit at position p to 0. Print the resulting number.)
Задачата е от упражнението, не от домашната. Изчетох всички разяснения, които сте писали и схванах как горе долу работят побитовите оператори. Въпроса ми тук е, че не мога да открия грешката си в задачата (или може би няма такава), а има грешка в примерните отговори, дадени в задачата, добавих ги след решението. 111 ми се получава отговора, но останалите - не. Помъчих се доста време, но не успях да се справя. Така че ако може малко помощ.
class BitDestroyer
{
static void Main(string[] args)
{
Console.WriteLine("Write a number n:");
int n = int.Parse(Console.ReadLine());
Console.WriteLine("Write a position p:");
int p = int.Parse(Console.ReadLine());
long result = long.Parse(Convert.ToString(n, 2));
long mask = n << p;
long invertmask = ~mask;
long newNumber = n & mask;
Console.WriteLine(newNumber);
}
}
n - p - Result
1313 - 5 - 1281
231 - 2 - 227
111 - 6 - 47
пробах твоя код с 111 и ми даде отговор 64.
Маската трябва да е единица, преместена на позицията на търсения бит.
Така както си го написал събираш n с преместен n.
за да сработи, трябва да си направиш маска от 1, преместена на нужната позиция. После си правиш тилда от маската, за да остане 0 под нужния бит и 1 под всички останали. И &. Така само където е било 1 в оригиналтото число, при & 0 дава 0, тоест the bit is destroyed. Всички други битове при & с 1ците на маската не се променят.
Не знам дали обеснението ми е ясно, дано помогнах.
Моето решение е това:
int n = int.Parse(Console.ReadLine());
int p = int.Parse(Console.ReadLine());
int mask = ~(1 << p);
int result = n & mask;
Console.WriteLine(result);
Благодаря много, че помогна :)
Това е моето решение, но ще пробвам и това на Светлин.
static void Main()
{
int n= int.Parse(Console.ReadLine());
int p = int.Parse(Console.ReadLine());
int movedNum = n >> p;
int bit = movedNum & 1;
Console.WriteLine(bit);
}
14-та е малко трики - трябва да обърнеш внимание на следното:
за да смениш стойността на бита ползваш маска ( int mask = 1 << p;), но задаваш в условна конструкция два случая за двете стойности на бита:
if (v == 0)
{
int result = n & (~mask);
Console.WriteLine(Convert.ToString(result, 2).PadLeft(16, '0'));
Console.WriteLine("The changed number in decimal is {0}", result);
}
else
{
int result2 = n | mask;
Console.WriteLine(Convert.ToString(result2, 2).PadLeft(16, '0'));
Console.WriteLine("The changed number in decimal is {0}", result2);
}
ако искаш да смениш бита с 0 трябва да ползваш оператора при заместване (когато сравняваш старото число с маската) и инвертирана маска (~mask); разписвам ти го, за да стане по-ясно (и на мен така ми го обясниха):
00001111 - това е числото 15 в бинарен вид
- маската за променяне на единицата в нула на 3та позиция (позициите броим от дясно на ляво, започвайки от 0) int mask = 1 << p; маската изглежда така: 00001000
11110111 - инвертираната маска изглежда така
00000111 - това е числото с променен бит -> извежда се като сравняваме първоначалното число и инвертираната маска с оператора '&', който дава 1 само когато има две единици, т.е. 1&1 = 1:
ако искаш да смениш бита с 1 трябва да ползваш оператора "|" при заместване и да си ползваш нормалната маска (int result2 = n | mask;).
Разгледай таблиците с резултатите от побитните оператори:
(с '&' ти връща 0 във всеки случай с изключение на 1&1 = 1);
(с '|' ти връща 1 във всеки случай с изключение на 0&0 = 0).
@tinta, може и без условна конструкциия. Просто винаги чистиш въпросния бит и след това веднага го установяваш в каквото ти е зададено: n= n & (~ (1 << p)) | (1 << v).
Нещо не ми се получава резултат 512, при n=0, p=9 и v=1 когато използвам n= n & (~ (1 << p)) | (1 << v), за другите два примера обаче, някак излиза резултата. Някой може ли да поясни, как точно би следвало да работи по този начин ?
using System;
class ModifyABitAtGivenPosition
{
static void Main()
{
while (true)
{
Console.WriteLine("Please enter integer number");
int n = int.Parse(Console.ReadLine());
Console.WriteLine("Please enter the position of the bit you would like to extract");
int p = int.Parse(Console.ReadLine());
byte v = 0;
do
{
Console.WriteLine("Please enter value of 1 or 0 for the bit you would like to exchange");
v = byte.Parse(Console.ReadLine());
} while (v != 0 && v != 1);
n = n & (~(1 << p)) | (1 << v);
Console.WriteLine(n);
}
}
}