Рейтинг:0

Деление большого числа в bash возвращает неверный результат

флаг in

Я пытаюсь преобразовать очень большое количество байтов в гигабайты.

эхо $(( 41003021288998461440 / 1073741824 ))

Это возвращает 3827300985. Это неверно. Правильный ответ будет 38187039354. 11 цифр против 10.

Использование другого «масштаба = 30» или прохождение через bc не меняет ответ. Что я делаю не так?

В качестве альтернативы я попробовал это:

awk -v var1=41003021288998461440 -v var2=1073741824 'НАЧАЛО {print (var1 / var2)}' OFMT='%25g'

Который возвращает «3,8187e+10», что кажется правильным в числовом отношении, но тогда я не могу понять, как не попасть в научное обозначение. Printf "%12d" не помогает, поскольку не может обработать деление в переданном параметре.

Я подозреваю, что исправить проблему научной нотации awk, вероятно, будет проще, но я все же хотел бы знать, почему длинное деление с эхом просто возвращает совершенно неправильный результат. Это очень важно, и, поскольку я часто выполняю вычисления таким образом, я хотел бы знать, что мне нужно сделать, чтобы эхо вычислялось точно.

Я также знаю, что однажды исправил проблему... но я потерял, как я это сделал, и теперь не могу вспомнить, вздох.

muru avatar
флаг us
В версии awk `printf "%12f", ( var1 / var2 )` дает мне `38187039353.883324`, а `%12d` дает `38187039353`
флаг hr
Я думаю, что ваше назначение OFMT в awk не выполняется, потому что (по крайней мере, в GNU awk) оно вступает в силу только после выполнения блока BEGIN: либо используйте `-v OFMT='%d'`, либо добавьте его внутрь блока `BEGIN { ОФМТ="%d"; напечатать (переменная1/переменная2)}`. См. [Назначение переменных в командной строке] (https://www.gnu.org/software/gawk/manual/gawk.html#Assignment-Options).
флаг hr
... в старых версиях GAWK вам также может потребоваться явно включить поддержку произвольной точности с помощью параметров `-M` или `--bignum`
Рейтинг:1
флаг us

Баш целые числа не произвольная точность:

Оценка выполняется в целых числах фиксированной ширины без проверки на переполнение, хотя деление на 0 перехватывается и помечается как ошибка.

Вероятный верхний предел в современных системах будет 2 ^ 63 для целых чисел со знаком:

$ эхо $ (( 2 ** 63 - 1 ))
9223372036854775807
$ эхо $ (( 2 ** 63 ))
-9223372036854775808
$ эхо $ (( 2 ** 62 ))
4611686018427387904 

Ваше число слишком велико (~ 4x) для этого. Если вы хотите выполнять арифметику случайной произвольной точности в интерактивном режиме, используйте Python:

>>> 41003021288998461440 / 1073741824
38187039353.88332
Рейтинг:0
флаг in

Наконец-то реконструировал, как сделать, чтобы он точно рассчитывал. И да, это включало использование «масштаба».

BYTECOUNT=$(echo "масштаб=0; (($BYTECOUNT/1073741824))" | bc)

Вышеприведенное сработало (с BYTECOUNT, ранее установленным на очень большое начальное число). Странно, что масштаб = 0 необходим, поскольку я считаю, что это должно быть значение по умолчанию, но кажется необходимым сделать его явным, чтобы расчет был правильным.

Рейтинг:0
флаг bd

Я считаю, что лучше всего использовать dc для этого:

V=$(эхо "8 k 41003021288998461440 1073741824 / p" | dc)
эхо $V

Это устанавливает точность на 8, делит следующие два значения, а затем извлекает их из стека.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.