Problems when dividing large numbers

Hi,
I have a code to convert Integers to Binary in order to send it with 433MHz later.
My number is 70110001.
When I devide it by 2 it gives me 35055000.00, which is wrong. It should result 35055000.50
If I divide 7011001 by 2 it gives me the right result.

Is the number to long for float? I can´t figure out what I am doing wrong.

I test the devision with this:
Serial.println((float)number / 2.0);

This is my Code:

const long number = 70110001;
// 70110001
// String binary = "100001011011100101100110001";

String message;

float newNumber;

float fdivided ;
long ldivided ;

void setup() {
  Serial.begin(112500);
}

void loop() {
  Serial.println("START");

  message = "";
  fdivided = number / 2.0;
  ldivided  = number / 2;
  Serial.println("+++++++++++++++++++++++++++++++");
  Serial.println((float)number / 2.0);


  while (1) {
    if ((fdivided - ldivided ) > 0) {
      message = "1" + message;
    }
    else if (ldivided == 0) {
      break;
    }
    else if ((fdivided - ldivided) == 0) {
      message = "0" + message;
    }

    Serial.println("+++++++++++++++++++++++++++++++");
    Serial.println(fdivided);
    Serial.println(ldivided);
    Serial.println(fdivided - ldivided);
    Serial.println(message);
    newNumber = ldivided;
    fdivided = newNumber / 2.0;
    ldivided = newNumber / 2;

  }

  Serial.println(message);

  delay(7000);

}

Thanks

naitsimp:
Hi,
I have a code to convert Integers to Binary in order to send it with 433MHz later.

your number is already stored in binary.

Try sprintf()

  fdevided = (float)number / 2.0;

The cast is unnecessary. Since one of the operands is a float, the result will BE a float.

We need to see your actual serial output, not your summary of it.

Anonymous printing sucks. For debugging purposes, it is well worth the few nanoseconds it takes to print identifying information before the value.

Do you really need to use floating point numbers? Floating point maths is very slow on an Arduino.

With integer maths you can divide by powers of two simply by right-shifting.

What are you sending the data to?

...R

Robin2:
With unsigned integer maths you can divide by powers of two simply by right-shifting.

Floating point can only represent a finite number of significant digits. The mantissa of a 'float' is 23 bits plus the implicit high-order 1. To represent 70110001 in binary requires 26 bits which won't all fit in a 'float' and you lose 2 of the low order bits.
Representing 7011001 in binary requires 23 bits and will therefore fit.
The division by two has no effect since this only changes the value of the exponent.

Pete

BulldogLowell:
With unsigned integer maths you can divide by powers of two simply by right-shifting.

Nope, it works with signed data also, the compiler handles that correctly.

unsigned long ulValue = 222222;
long lValuePositive = 222222;
long lValueNegative = -222222;
void setup() {
  Serial.begin(250000);
  Serial.print(F("unsigned "));
  Serial.print(ulValue);
  Serial.print(F(" >> 1  = "));
  Serial.println(ulValue >> 1);
  Serial.print(F("signed + "));
  Serial.print(lValuePositive);
  Serial.print(F(" >> 1  = "));
  Serial.println(lValuePositive >> 1);
  Serial.print(F("signed - "));
  Serial.print(lValueNegative);
  Serial.print(F(" >> 1  = "));
  Serial.println(lValueNegative >> 1);
}
void loop() {}
unsigned 222222 >> 1  = 111111
signed + 222222 >> 1  = 111111
signed - -222222 >> 1  = -111111

Whandall:
it works with signed data also, the compiler handles that correctly.

That is implementation-defined. GCC uses sign extension with negative values, but some other compiler might behave differently.

I would use '/' anyway because it is less to type, more readable and works on any compiler.

For reasons mentioned earlier, the number 70110001 may or may not be accurate represented as a float. Because only 4 bytes are used for floating point numbers, the precision of a floating point number is about 7 digits. Anything after the first 7 digits is the computer's best guess as to the actual number. This is one area where the C supported by the Arduino IDE differs from a "full" (ANSII) C compiler, in that the IDE does not support a true double data type, which is 8 bytes. If it did, you could probably get 15 digits of precision.

Also, next time when you post your code, please place the code in code tags, as explained in Nick Gammon's post on using this Forum, which are found at the top of this Forum.

"My number is 70110001."

That fits both signed and unsigned long integers.

When you do integer division it does cut the remainder but note that the modulo operator returns the remainder.

70110001 / 2 = 35055000 --- integer division

70110001 % 2 = 1 ---- integer modulus, 1/2 is the fraction.

You can get exact answers with integers or inexact answers with floats and very few operations.

oqibidipo:
That is implementation-defined. GCC uses sign extension with negative values, but some other compiler might behave differently.

It is not implentation-defined, sign extension is a defined part of the C language. This is why C provides bot a >> and a >>> operator.

My number is 70110001.
When I devide it by 2 it gives me 35055000.00, which is wrong. It should result 35055000.50

O…kay.

Floating point numbers should always be treated as being an approximation of some real number. If you need things to be calculated exactly to the digit, then use an integer.

Integers, of course, don't handle fractional results. The fix for this is to handle your quantities as multiples of the smallest fraction you will need to deal with. When handling currency, for instance, store amounts as an integer quantity of cents. When dealing with time, store amounts as a number of minutes or even a number of seconds.

Other languages provide fixed-point aritmetic, eg the sql NUMBER(10,2) type. C doesn't

PaulMurrayCbr:
O…kay.

Floating point numbers should always be treated as being an approximation of some real number. If you need things to be calculated exactly to the digit, then use an integer.

Other languages provide fixed-point aritmetic, eg the sql NUMBER(10,2) type. C doesn't

Not to mention the Precision of that big number...

PaulMurrayCbr:
It is not implentation-defined, sign extension is a defined part of the C language. This is why C provides bot a >> and a >>> operator.

This is 100% rubbish.

There is no >>> operator in C/C++.

C11 standard (N1570 final draft PDF)

6.5.7 Bitwise shift operators

Syntax

  • shift-expression: additive-expression*
  • shift-expression << additive-expression*
  • shift-expression >> additive-expression*
    ...
    The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

It is no different in C++.

GCC Documentation
4 C Implementation-defined behavior
4.5 Integers (GCC 4.9.4 | 8.1.0)

The results of some bitwise operations on signed integers (C90 6.3, C99 and C11 6.5).

Bitwise operators act on the representation of the value including both the sign and value bits, where the sign bit is considered immediately above the highest-value value bit. Signed ‘>>’ acts on negative numbers by sign extension.

Thank you all for help. Thank you.
It looks like that it is not possible to divide my number (70110001) and have a float data type because the float number would be too big for this data type. A pitty.
Hence this restriction I will have to make the number one digit smaller.

naitsimp:
It looks like that it is not possible to divide my number (70110001)
and have a float data type because the float number would be too big for this data type.

No. Floats can be much larger, but 4 byte floats 'only' have six significant digits.

If you care for exact numbers use an integral type.
If you need fractional parts, you can interpret it as 1/10, 1/100 or 1/1000.

Your number 70 110 001 fits perfectly into a long, which gives you 9 full digits.

Why do you want to use a float?

What is your division result used for?

I am converting a Number to Binary and send this binary with a 433Mhz Module.
IN order to convert it I need to know if the division has a Remainder or not.

I calculate it like in the first table on this site: Decimal to Binary Converter
If Remainder -> 1
If no Remainder -> 0

I am converting a Number to Binary

Why?
The number already is binary

naitsimp:
I am converting a Number to Binary and send this binary with a 433Mhz Module.
IN order to convert it I need to know if the division has a Remainder or not.

I calculate it like in the first table on this site: Decimal to Binary Converter
If Remainder -> 1
If no Remainder -> 0

The C++ Modulus Operator

if (someNum % 2) {
  Serial.println("Has Remainder");
} else {
  Serial.println("No remainder");
}