wcminipgasker2023
wcminipgasker2023

Reputation: 199

Without overflow and underflow, for a float number x, is x/4 always equals to x/2/2 (also for x*4 == x*2*2)?

For example, as I know, a float point x, which x/n^2 may not be equal to x/n/n, because in x/n/n, which would create an intermediate x/n first. For example:

document.write(1.23456789/49 == 1.23456789/7/7);

However, is x/4 == x/2/2 an exception, if no overflow and underflow, which is always true?

I tested:

document.write(1.23456789/4 == 1.23456789/2/2);

Also for binary:

Binary of 1.23456789 (actual float : 1.2345678806304931640625) :

0 01111111 00111100000011001010010

binary of 0.61728394031524658203125 (1.2345678806304931640625/2)

0 10000000 00111100000011001010010

which seems when multiply only varies the "exponent" part (01111111 to 10000000), keeping the fraction part unchanged (00111100000011001010010).

So currently I have a "hypothesis" : for float number x without overflow and underflow, x/4 should always be equal to x/2/2, also for x * 4==x * 2 * 2, is that true?

Upvotes: 1

Views: 100

Answers (3)

Eric Postpischil
Eric Postpischil

Reputation: 222942

Without overflow and underflow, for a float number x, is x/4 always equals to x/2/2 (also for x4 == x2*2)?

This is true in the floating-point format JavaScript uses, but it is not true in floating-point formats generally.

A finite floating-point number is represented as ±fbe, where:

  • b is a fixed base for the format.
  • p (used below) is the precision of the format, a number of digits.
  • f is an integer expressible with p digits in base b.
  • e is an integer in a range emineemax for some emin and emax that are fixed limits for the format.

(Floating-point formats are often also described with f having a radix point before or after its first digit, so that it is not always an integer and is in an interval such as [1, b[ or [1/b, 1[. However, the exponent limits are adjusted accordingly, and these descriptions are mathematically equivalent. Scaling f to be an integer is useful for number theory proofs of floating-point properties.)

A floating-point operation produces a result as if the result of the corresponding real-number operation were rounded to the nearest representable number, according to some rounding rule, most commonly to round to nearest with ties to the representable number with an even low digit (or, if neither has an even low digit, the one with greater magnitude).

JavaScript uses a binary format (b is 2). With a binary format, the real-number result of dividing ±fbe by 4 is ±fbe−2. Since we are given there is no underflow, e−2 is in the range from emin to emax, so ±fbe−2 is representable in the format, so it is the closet representable to the real-number result, so it is the result produced by floating-point division by 4. Similarly, the real-number result of dividing by 2 is ±fbe−1, which is representable, so it is the result of floating-point division. And then dividing that by two produces ±fbe−2. So we see the result of dividing any representable finite number by 4 equals the result of dividing it by 2 twice. (We can also check that this holds for things other than finite numbers; it holds for ±∞ and for a NaN.)

However, some software uses other floating-point formats. Consider base 10 with p = 3, and take the representable number +345•100. In this format, the real-number result of dividing by 4 is +86.25•100 = +862.5•10−1, so the floating-point result is the nearest representable value, +862•10−1. When we divide +345•100. by 2, the real-number result is 172.5•100. Here, both 172•100 and 173•100 are equally close, so the floating-point result is the one with the even low digit, 172•100. When we divide that by 2, the real-number result is 86•100, and that is representable, so it is the floating-point result.

Thus, with a three-digit base-ten format, 345/4 yields 86.2, but 345/2/2 yields 86.

Upvotes: 0

vinc17
vinc17

Reputation: 3476

Without overflow and underflow, since the radix is 2, multiplications and divisions by powers of 2 are always exact operations. Since no rounding is involved here, x/4 is equal to x/2/2 and x*4 is equal to x*2*2, as this is true on the real numbers.

Note that if x is ±0, the sign of the result will be the same with both expressions.

EDIT: More generally, in each expression, you may have a single multiplication or division by a number that is not a power of 2. For instance, x/2/3 and x/3/2 are always equal to x/6.

Upvotes: 1

gl00ten
gl00ten

Reputation: 1121

I thought it would be only true for powers of 2. So I tried with your float and other prime numbers and found that it was apparently only not true for 7?, so decided to brute force it.

function testEqualityForRandomNumbers(iterations, f) {
  let equalCount = 0;
  const failedTests = [];

  for (let a = 1; a <= iterations; a++) {
    
    const leftSide = (f / a) / a;
    const rightSide = f / (a * a);
    if (leftSide == rightSide) {
      equalCount++;
    } else {
      failedTests.push(a);
    }
  }
  return failedTests;
}

function removeFailedTests(digits, digitsToRemove) {
  let allDigits = Array.from({ length: digits }, (_, i) => i + 1);

  for (let i = 0; i < 10000; i++) {

    const f = Math.random() + 1;
    const failedTests = testEqualityForRandomNumbers(digits, f);
    
    // Remove the digits that have failed the test
    allDigits = allDigits.filter((digit) => !failedTests.includes(digit));

    
    // If no more digits are left, stop the process
    if (allDigits.length === 0) {
      console.log('All digits have failed the test.');
      break;
    }
  }
  console.log(allDigits)
  
}

const digits = 10000;
removeFailedTests(digits);


[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]

For random float numbers, yeh, only exponents of two survive. But at this point I'm more curious about the 7 and your 1.23456...

Upvotes: 0

Related Questions