Операции с плавающей запятой с помощью bc неточны?

libc использует /etc/nsswitch.conf для настройки разрешения имен. см. man nsswitch.conf

, если в какой-то момент запись о ваших хостах разрешена с использованием dns, эта подсистема будет читать /etc/resolv.conf в поисках параметров.

рассмотрите возможность использования только локального кэша DNS для ускорения DNS. Если dnsmasq считается слишком большим, вы можете напрямую использовать статический файл / etc / hosts для разрешения имен.

для ускорения увеличения скорости передачи данных вам следует подумать об использовании протокола Spanning Tree Portfast на коммутаторе, ведущем к этому интерфейсу на вашем PI.

4
02.05.2016, 16:39
2 ответа

Вам необходимо понять значение масштаба выражения в bc . bc может выполнять произвольную точность (что не обязательно означает бесконечную точность), в то время как ваш калькулятор , вероятно, будет иметь точность float или двойной тип данных вашего процессора.

В до н.э. . Масштаб - это число после запятой после запятой, поэтому оно связано с точностью. Масштаб выражения определяется на основе правил, которые зависят от того, какой оператор задействован, и переменной scale (именно эта переменная дает произвольное измерение точности из bc , то есть это может сделать его точность сколь угодно большой).

Например, масштаб результата деления - масштаб . Итак, 4/3 , когда масштаб равен 2, составляет 1,33 , так что это очень грубое приближение 4/3 . Масштаб x * y будет min (a + b, max (scale, a, b)) (где a - масштаб ] x и b масштаб y ), поэтому здесь 2 . поэтому 1.33 * 3.14 будет 4.17 .

Правила можно найти в спецификации POSIX для bc .

Если вам нужна более высокая точность, увеличьте масштаб . Вы можете увеличивать его до бесконечности.С bc -l , масштаб автоматически устанавливается на 20 .

$ pi='(a(1)*4)' r=3
$ $ echo "(4 / 3) * $pi * ($r ^ 3)" | bc -l
113.09733552923255658339

$ echo "scale=1000; (4 / 3) * $pi * ($r ^ 3)" | bc -l
113.0973355292325565846551617980621038310980983775038095550980053230\
81390626303523950609253712316214447357331114478163039295378405943820\
96034211293869262532022821022769726978675980014720642616237749375071\
94371951239736040606251233364163241939497632687292433484092445725499\
76355759335682169861368969085854085132237827361174295734753154661853\
14730175311724413325296040789909975753679476982929026989441793959006\
17331673453103113187002257495740245517842677306806456786589844246678\
87098096084205774588430168674012241047863639151096770218070228090538\
86527847499397329973941181834655436308584829346483609858475202045257\
72294881898002877683392804259302509384339728638724440983234852757850\
73357828522068813321247512718420036644790591105239053753290671891767\
15857867345960859999994142720979823815034238137946746942088054039248\
86988951308030971204086612694295227741563601129621951039171511955017\
31142218396089302929537125655435196874321744263099764736353375070480\
1468800991581641650380680694035580030527317911271523

$ echo "scale=1; (4 / 3) * $pi * ($r ^ 3)" | bc -l
97.2

Вы также можете выполнять все свои вычисления с высоким масштабом и уменьшать его в конце для отображения:

$ echo "scale=10; (4 / 3) * $pi * ($r ^ 3)" | bc -l
113.0973355107
$ echo "scale=100; x = (4 / 3) * $pi * ($r ^ 3); scale = 10; x / 1" | bc -l
113.0973355292
14
27.01.2020, 20:46

Следует использовать лучшее значение для pi и разрешить масштабирование, как определено по умолчанию в bc (20 цифр):

$ echo "r=3; pi=4*a(1); (4/3)*pi*(r^3)" | bc -l
113.09733552923255658339

Это лучший способ выполнения вычисления. Масштаб — это параметр для определения точности, используемой в вычислении, а не параметр для форматирования числовых выходных данных результата.

Для форматирования числа можно использовать printf:

$ result="$(echo "r=3; pi=4*a(1); (4/3)*pi*(r^3)" | bc -l)"
$ printf '%.2f' "$result"
113.10

Если у вас возникли проблемы с числовым десятичным символом (, или . ), вы можете использовать эту версию:

$ LC_NUMERIC=C printf '%.2f' "$result"
113.10

printf округляет число после реализации IEEE 754

Конечно, вы можете заставить bc вырезать десятичные дроби с окончательным изменением масштаба:

$ echo "r=3; pi=4*a(1); res=(4/3)*pi*(r^3); scale=2; res/1" | bc -l
113.09

Но это плохая идея в целом.

1
27.01.2020, 20:46

Теги

Похожие вопросы