Конвертировать Binary в Integer

Vinch
Offline
Зарегистрирован: 01.08.2013

есть строка String s1 = "111110010101";

и хочу чтобы получился результат int i = 3989;

Подскажите как реализовать?

axill
Offline
Зарегистрирован: 05.09.2011

построить цикл по сканированию строки по одному символу слева направо. перед циклом объявить переменную int присвоив ей 0. на каждой итерации цикла выставляем нулевой бит исходя из того есть единица в сканированном символе или нет и сдвигаем число влево

Datak
Offline
Зарегистрирован: 09.10.2014






int i = 0;
for( int Pos = 0; s1[Pos] != 0; Pos++ )
{
   i = ( i << 1 ) | ( s1[Pos] - '0' );
}

Так, что ли, получается? :)

Vinch
Offline
Зарегистрирован: 01.08.2013

Долго мучился и в итоге получилось вот так:

int BinToInt(String st) {
  int i, stLen;
  int Result = 0;
  stLen = st.length();
   for (int a = stLen; a > 0 ; a-- ) {
    if (st[a-1] == '1') {
    i = 1 << ((stLen-1)-(a-1));
    Result = Result + i;
    }
   }
   return Result;
}

 

Vinch
Offline
Зарегистрирован: 01.08.2013
Появилась новая проблема:
пытаюсь конвертировать 110110010110001010110111
должно получится 14 246 583, но получается 25271 исправил int на long, но ничего не изменилось..
вот так выглядит лог
110110010110001010110111
1
2
4
16
32
128
512
8192
16384
0
0
0
0
0
 

 

sva1509
Offline
Зарегистрирован: 07.12.2012

Я думаю, где то так:

unsigned long conv(char *str)
{
        unsigned long l1=0;
        while(*str) l1 = (l1 << 1) | (unsigned long) (*str++ - 48);
        return l1;
}

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Vinch пишет:

Появилась новая проблема:
пытаюсь конвертировать 110110010110001010110111
должно получится 14 246 583, но получается 25271 исправил int на long, но ничего не изменилось..
вот так выглядит лог
 

unsigned long - 8 байта , long - 4 байта , ...................

BIN 110110010110001010110111  >>>  HEX D962B7 ( ЭТО 6 БАЙТ )  >>>  DEC 14246583

выделенное откусит разрядная сетка представления чисел, и останется вот так

BIN 0110001010110111  >>>  HEX 62B7 ( ЭТО 4 БАЙТа )  >>>  DEC 25271

всё правильно МК сделал :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

чёта покурепалось всё....

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Vinch пишет:

Долго мучился и в итоге получилось вот так:

int BinToInt(String st) {
  int i, stLen;
  int Result = 0;
  stLen = st.length();
   for (int a = stLen; a > 0 ; a-- ) {
    if (st[a-1] == '1') {
    i = 1 << ((stLen-1)-(a-1));
    Result = Result + i;
    }
   }
   return Result;
}

#1 - unsigned long

#2 - unsigned long и byte

#3 -unsigned long

#5 - byte

Vinch
Offline
Зарегистрирован: 01.08.2013

SU-27-16 пишет:

Vinch пишет:

Долго мучился и в итоге получилось вот так:

int BinToInt(String st) {
  int i, stLen;
  int Result = 0;
  stLen = st.length();
   for (int a = stLen; a > 0 ; a-- ) {
    if (st[a-1] == '1') {
    i = 1 << ((stLen-1)-(a-1));
    Result = Result + i;
    }
   }
   return Result;
}

#1 - unsigned long

#2 - unsigned long и byte

#3 -unsigned long

#5 - byte

unsigned long BinToInt(String st) {
  byte stLen;
  unsigned long i,Result = 0;
  stLen = st.length();
   for (byte a = stLen; a >0 ; a-- ) {
    if (st[a-1] == '1') {
    i = 1 << ((stLen-1)-(a-1));
    Serial.println(i);
    Result = Result + i;
    }
   }
   return Result;
}

Результат остался прежний..

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Vinch пишет:

Долго мучился и в итоге получилось вот так:

int BinToInt(String st) {
  int i, stLen;
  int Result = 0;
  stLen = st.length();
   for (int a = stLen; a > 0 ; a-- ) {
    if (st[a-1] == '1') {
    i = 1 << ((stLen-1)-(a-1));
    Result = Result + i;
    }
   }
   return Result;
}

 

я думал ЭТО работает... вот и допеределал :( 

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Если не работает всегда можно сделать как в школе на бумажке делали :) Оно всегда работает.

unsigned long BinToInt(String st)
{
  byte stLen;
  unsigned long i,Result = 0;
  stLen = st.length();  
  for (byte a = 0; a < stLen; a++)
  {
    if (st[a] == '1')
    {
      Result += mypow(2, (stLen-1-a));
    }
  }
  return Result;
}

unsigned long mypow(byte base, byte exponent)
{
  unsigned long Result = 1;
  for(byte i=1;i<=exponent;i++)
    Result *= base;
  return Result;
}

Стандартная pow() точность не даёт, поэтому её использовать не получится, результат будет неточным.

Другое дело если надо красивый локаничный код :)

noxic
Offline
Зарегистрирован: 15.03.2013
SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Penni пишет:

Другое дело если надо красивый локаничный код :)

а если надо для слома мозгов ? поможете ?

задумка такая - адрес строки как массива известен, длину строки - через sizeof() , в массив на 4 байта ( 8 байтов ) запихнуть эту строку, выравнивая по правому краю ( 0=х30=b0011000 , 1=х31=b0011001 нулевой бит символа 0 или 1 писать в байт и двигать его ) ,

а потом интерпретировать этот массив как int ( unsigned long )...

ну, и ещё вопрос - как float распихана по 8-ми байтам в ардуине ? Число в формате ПТ или ЧФПТнормализованное ? Или ардуина знакома со стандартом на числа ПТ ANSI/IEEE 754-1985 - Short Real ?

Очень хочется распотрошить , например , 165.762545 - что да как там по байтам....

Спасибо :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

через так 

union CharInt { char ar[ 9 ]; int n; };

возможный путь решения ?

Vinch
Offline
Зарегистрирован: 01.08.2013

Penni пишет:

Если не работает всегда можно сделать как в школе на бумажке делали :) Оно всегда работает.

unsigned long BinToInt(String st)
{
  byte stLen;
  unsigned long i,Result = 0;
  stLen = st.length();  
  for (byte a = 0; a < stLen; a++)
  {
    if (st[a] == '1')
    {
      Result += mypow(2, (stLen-1-a));
    }
  }
  return Result;
}

unsigned long mypow(byte base, byte exponent)
{
  unsigned long Result = 1;
  for(byte i=1;i<=exponent;i++)
    Result *= base;
  return Result;
}

Стандартная pow() точность не даёт, поэтому её использовать не получится, результат будет неточным.

Другое дело если надо красивый локаничный код :)

 

Сидел, думал, исправлял и получилось подлиннее, но только так)

unsigned long BinToInt(String st) {
  byte stLen;
  unsigned long i,Result = 0;
  stLen = st.length();
   for (byte a = stLen; a >0 ; a-- ) {
    if (st[a-1] == '1') {
    i = shl((stLen-1)-(a-1));
    Result = Result + i;
    }
   }
   return Result;
}

unsigned long shl(byte by) {
 unsigned long p;
   if (by == 0) p = 1;
   else if (by == 1) p = 2;
 else {
   p = pow(2,by);
   if (p%2 != 0) p = p + 1;
   if (by == 20) p = 1048576;
   if (by == 22) p = 4194304;
   if (by == 23) p = 8388608;
   if (by == 24) p = 16777216;
 }
   return p;
}

Единственное что не понял, это почему pow() работает так непонятно..

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Ну тут я Вам не помогу, давно это всё было и неправда :) Помню как я не любил когда нам давали числа с плавающей точкой, а нам надо было на листике представить их так как они лежат в памяти ЭВМ :) Я с ардуино по работе не связан, так для себя мелочи всякие делаю. А коллега на работе (который ардуино заведует) говорит, что float вообще не использует, вместо них хранит в лонгах мантису экспоненты и собирает всё как ему надо, говорит быстро и самое главное точно.

Видел на arduino.cc выкладывали функции IEEE754 для работы с 32 и 64 бита

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Vinch пишет:

Единственное что не понял, это почему pow() работает так непонятно..

она оперирует float а у него точность 6-7 знаков, если, например, написать pow(2, 23) получите не тоже самое что на калькуляторе

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Penni пишет:

...... А коллега на работе (который ардуино заведует) говорит, что float вообще не использует, вместо них хранит в лонгах мантису экспоненты и собирает всё как ему надо, говорит быстро и самое главное точно.

Видел на arduino.cc выкладывали функции IEEE754 для работы с 32 и 64 бита

тоже хотел бы поиграть с точностью :) , спасибо !

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 от sva1509 - 2674 bytes / 25 mSec

char str1[ 33 ]  = "11111111111111111111111111111111";
unsigned long out;
//=====================================
void setup()
{    
   Serial.begin( 9600 );
}
//=====================================
void loop()
{
  unsigned long T = millis();
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  for ( int i = 0; i < 500; i++ )      //>>
    {                                  //>>
      out = conv( str1 );              //>>
    }                                  //>>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  Serial.println( millis() - T );
  Serial.println( out );
  delay( 500 );
}
//=====================================
unsigned long conv( char *str )
{
  unsigned long l1 = 0;
//  while( *str ) l1 = ( l1 << 1 ) | ( unsigned long ) ( *str++ - 48 );
  while( *str ) l1 = ( l1 << 1 ) | ( *str++ - 48 );
  return l1;
}
//=====================================

у миня получилось только так :( - 2696 bytes / 30 mSec

char str1[ 33 ]  = "11111111111111111111111111111111";
unsigned long out;
  union CharInt
  {
    unsigned long intN;
    char strN[ 33 ];
  };
  CharInt abc = { 0x0000000000000000 };
//=====================================
void setup()
{    
  Serial.begin( 9600 );
}
//=====================================
void loop()
{
  unsigned long T = millis();
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  for ( int i = 0; i < 500; i++ )      //>>
{                                      //>>
  out = binToLong( str1 );             //>>
}                                      //>>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  Serial.println( millis() - T );
  Serial.println( out );
  delay( 500 );
}
//=====================================
unsigned long binToLong( char *str )
{
  int i = 0;
  while ( str1[ i ] != NULL )
    {
      abc.intN <<= 1;
      abc.strN[ 0 ] = abc.strN[ 0 ] | ( str1[ i ] & 0x01 );
      i++;
    }
  return abc.intN;
}
//=====================================
/*
unsigned long binToLong( char *str )
{
  char *strTemp;
  strTemp = & abc.strN[ 0 ];
  while ( *str != NULL )
    {
      abc.intN <<= 1;
      *strTemp = *strTemp | ( *str++ & 0x01 );
    }
  return abc.intN;
}
*/
//=====================================

 

sva1509
Offline
Зарегистрирован: 07.12.2012

Доброго времени суток !

а попробуйте еще так :

char str1[ 33 ]  = "11111111111111111111111111111111";
unsigned long out;
//=====================================
void setup()
{    
   Serial.begin( 9600 );
}
//=====================================
void loop()
{
  unsigned long T = millis();
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  for ( int i = 0; i < 500; i++ )      //>>
    {                                  //>>
      //out = conv( str1 );              //>>
         while( *str ) out = ( out << 1 ) | ( *str++ - 48 );
    }                                  //>>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  Serial.println( millis() - T );
  Serial.println( out );
  delay( 500 );
}

просто интересно что получится.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

сначала понять надо :) 

sva1509
Offline
Зарегистрирован: 07.12.2012

ваша конвертация все равно занимает одну строку, я вам просто заменил строку вызова функции на строку конвертации, что по идее должно ускорить процесс. К стати я допустил ошибку предварительно не обнулив out.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
char str1[ 33 ]  = "11111111111111111111111111111111";
unsigned long out;
char *str;
//=====================================
void setup()
{    
   Serial.begin( 9600 );
}
//=====================================
void loop()
{
  unsigned long T = millis();
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  for ( int i = 0; i < 500; i++ )      //>>
    {                                  //>>
//      out = conv( str1 );              //>>
  out = 0;
  str = & str1;
  while( *str ) out = ( out << 1 ) | ( *str++ - 48 );      
    }                                  //>>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>char str1[ 33 ]  = "11111111111111111111111111111111";
unsigned long out;
char *str;
//=====================================
void setup()
{    
   Serial.begin( 9600 );
}
//=====================================
void loop()
{
  unsigned long T = millis();
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  for ( int i = 0; i < 500; i++ )      //>>
    {                                  //>>
//      out = conv( str1 );              //>>
  out = 0;
  str = & str1;
  while( *str ) out = ( out << 1 ) | ( *str++ - 48 );      
    }                                  //>>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

ага, исправил... и указатель не обьявили, только как его разыменовать или как там это называется :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
char str1[ 33 ]  = "11111111111111111111111111111111";
unsigned long out;
//char *str = str1;
char *str;
//=====================================
void setup()
{    
   Serial.begin( 9600 );
}
//=====================================
void loop()
{
  unsigned long T = millis();
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  for ( int i = 0; i < 500; i++ )      //>>
    {                                  //>>
//      out = conv( str1 );              //>>
//  char *str = str1;
//  *str = &str1;
  str = str1;
  out = 0;
  while( *str ) out = ( out << 1 ) | ( *str++ - 48 );      
    }                                  //>>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

если объявить и инициировать в строке 3 - не работает

если объявить и инициировать в строке 18 - работает , время тоже 25 mSec

если объявить в строке 4 , а и инициировать в лупе str = str1; - работает , но время 50 mSec

если объявить в строке 4 , а и инициировать в лупе str = &str1; - ругается

если объявить в строке 4 , а и инициировать в лупе *str = str1; - ругается

если объявить в строке 4 , а и инициировать в лупе *str = &str1; - ругается

все варианты преберал - но в книжке же пишут, что надо char *str = &str1;

почему не работает с амперсандом ?

как правильно объвить в секции определений, а инициировать в лупе ?

если char *str = str1; в верхней секции и char *str = str1; в лупе - это же два указателя ?

один глобальный, второй - локальный для лупа ?

спасибо ! :)

sva1509
Offline
Зарегистрирован: 07.12.2012

правильно объявлять str = str1; дело в том что имя массива это тоже указатель. Когда вы указываете &str1 это уже адрес адреса. Когда указываете *str это вы обращаетесь к данным по адресу str.