Используя bcdiv, я не могу разделить с небольшим поплавком, используя научную нотацию:
Рабочий код:
bcscale(30); $a = '1' ; $b = '0.00000001'; $result = bcdiv($a, $b); var_dump($result);
Результаты в:
строка (20) "100000000.0000000000"
Нерабочий код:
bcscale(30); $a = '1' ; $b = '1e-8'; $result = bcdiv($a, $b); var_dump($result);
Результаты в:
Предупреждение: bcdiv () [function.bcdiv]: Деление на ноль в C: \ wamp \ www \ utilitaires \ test_bcdiv.php в строке XX NULL
Как я могу сделать это разделение правильно, с меньшей точностью потери?
Это потому, что на самом деле bcmath
не поддерживает научную нотацию. Он не упоминается в руководствах, но, как вы можете видеть, в его применении используется преобразование аргумента, оно называется php_str2num
:
static void php_str2num(bc_num *num, char *str TSRMLS_DC) { char *p; if (!(p = strchr(str, '.'))) { bc_str2num(num, str, 0 TSRMLS_CC); return; } bc_str2num(num, str, strlen(p+1) TSRMLS_CC); }
и так bc_str2num
:
bc_str2num (bc_num *num, char *str, int scale TSRMLS_DC) { int digits, strscale; char *ptr, *nptr; char zero_int; /* Prepare num. */ bc_free_num (num); /* Check for valid number and count digits. */ ptr = str; digits = 0; strscale = 0; zero_int = FALSE; if ( (*ptr == '+') || (*ptr == '-')) ptr++; /* Sign */ while (*ptr == '0') ptr++; /* Skip leading zeros. */ while (isdigit((int)*ptr)) ptr++, digits++; /* digits */ if (*ptr == '.') ptr++; /* decimal point */ while (isdigit((int)*ptr)) ptr++, strscale++; /* digits */ if ((*ptr != '\0') || (digits+strscale == 0)) { *num = bc_copy_num (BCG(_zero_)); return; } /* Adjust numbers and allocate storage and initialize fields. */ strscale = MIN(strscale, scale); if (digits == 0) { zero_int = TRUE; digits = 1; } *num = bc_new_num (digits, strscale); /* Build the whole number. */ ptr = str; if (*ptr == '-') { (*num)->n_sign = MINUS; ptr++; } else { (*num)->n_sign = PLUS; if (*ptr == '+') ptr++; } while (*ptr == '0') ptr++; /* Skip leading zeros. */ nptr = (*num)->n_value; if (zero_int) { *nptr++ = 0; digits = 0; } for (;digits > 0; digits--) *nptr++ = CH_VAL(*ptr++); /* Build the fractional part. */ if (strscale > 0) { ptr++; /* skip the decimal point! */ for (;strscale > 0; strscale--) *nptr++ = CH_VAL(*ptr++); } }
-не трудно понять, что он потерпит неудачу в научной нотации (хорошо комментируется). Возможно, документация нуждается в обновлении (не говоря уже об этом).
Возможным решением будет преобразование вашей строки в простой вид перед применением функций bcmath