Zend Framework

bcmath extension used by Zend_Locale doesn't support scientific notation for floats representation.

Details

  • Type: Improvement Improvement
  • Status: Resolved Resolved
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 1.5.0RC1
  • Fix Version/s: 1.7.3
  • Component/s: Zend_Locale
  • Labels:
    None

Description

bcmath extension uses strings as an input.
Some floats are automatically written using scientific notation while they are converted to strings (like '1.234E-6').

bcmath extension skips exponent part of the number (e.g. '1.234E-6' => '1.234'). That produces wrong results of mathimatical operations with some numbers.

Hopefully, bcmath functions are not used directly within Zend Framework (except some big integers arithmetic within Zend_OpenId which is not affected by this problem). So we can proxy bcmath calls and perform correct numbers transformation.

That also may help to solve problems with some locales having ',' as decimal separator.

Issue Links

Activity

Hide
Maxence Delannoy added a comment -

We can solve this by adding this code to Zend_Locale_Math::normalize:

public static function normalize($value)
{
  [..]
  // Handle exponential notation
  $parts = preg_split('/e/i', $value);
  if (count($parts) > 1) {
    $value = bcmul($parts[0], bcpow(10, $parts[1]));
  }
  return $value;
}

Test :

$this->assertEquals('1000', Zend_Locale_Math::normalize('1e3'));
$this->assertEquals('1000', Zend_Locale_Math::normalize('1E3'));
$this->assertEquals('1234', Zend_Locale_Math::normalize('1.234E3'));
$this->assertEquals('0.001', Zend_Locale_Math::normalize('1e-3'));

$this->assertEquals('12', Zend_Locale_Math::round('1.23e1'));
$this->assertEquals('12.3', Zend_Locale_Math::round('1.23e1', 1));

Note : bcmath is required.

Show
Maxence Delannoy added a comment - We can solve this by adding this code to Zend_Locale_Math::normalize:
public static function normalize($value)
{
  [..]
  // Handle exponential notation
  $parts = preg_split('/e/i', $value);
  if (count($parts) > 1) {
    $value = bcmul($parts[0], bcpow(10, $parts[1]));
  }
  return $value;
}
Test :
$this->assertEquals('1000', Zend_Locale_Math::normalize('1e3'));
$this->assertEquals('1000', Zend_Locale_Math::normalize('1E3'));
$this->assertEquals('1234', Zend_Locale_Math::normalize('1.234E3'));
$this->assertEquals('0.001', Zend_Locale_Math::normalize('1e-3'));

$this->assertEquals('12', Zend_Locale_Math::round('1.23e1'));
$this->assertEquals('12.3', Zend_Locale_Math::round('1.23e1', 1));
Note : bcmath is required.
Hide
Maxence Delannoy added a comment -

Hopefully, bcmath functions are not used directly within Zend Framework

bcmath functions (and scientific notation) are used in Zend_Measure.

Show
Maxence Delannoy added a comment -
Hopefully, bcmath functions are not used directly within Zend Framework
bcmath functions (and scientific notation) are used in Zend_Measure.
Hide
Thomas Weidner added a comment -

There are several places where bcmath are used.
But your code can not be used, as it does not work when bcmath is not available.

You can not use bcmath functions on a class which is used as workaround when no bcmath is installed.

Show
Thomas Weidner added a comment - There are several places where bcmath are used. But your code can not be used, as it does not work when bcmath is not available. You can not use bcmath functions on a class which is used as workaround when no bcmath is installed.
Hide
Thomas Weidner added a comment -

Feature added with r13500

Show
Thomas Weidner added a comment - Feature added with r13500

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: