ฉันจะใช้การหารทศนิยมในวิธีทุบตีได้อย่างไร


242

ฉันพยายามแบ่งความกว้างของภาพสองภาพใน Bash script แต่ bash ให้0ผลลัพธ์ดังนี้:

RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))

ฉันศึกษาคู่มือ Bash และฉันรู้ว่าฉันควรใช้bcในตัวอย่างทั้งหมดที่พวกเขาใช้bcอินเทอร์เน็ต ในechoฉันพยายามที่จะใส่สิ่งเดียวกันในของฉันSCALEแต่มันไม่ทำงาน

นี่คือตัวอย่างที่ฉันพบในบทช่วยสอน:

echo "scale=2; ${userinput}" | bc 

ฉันจะได้รับ Bash เพื่อให้ฉันลอยได้0.5อย่างไร


9
ความคิดเห็นสำหรับทุกคนที่พยายามทำเลขคณิตจุดลอยตัวในสคริปต์ของคุณถามตัวเองว่า: ฉันต้องการเลขคณิตจุดลอยตัวจริงหรือไม่? บางครั้งคุณสามารถเข้ากันได้โดยปราศจาก ดูตัวอย่างเช่นส่วนสุดท้ายของBashFAQ / 022
gniourf_gniourf

คำตอบ:


242

คุณทำไม่ได้ ทุบตีเท่านั้นจำนวนเต็ม; คุณจะต้องbcมอบหมายให้เครื่องมือดังกล่าวเป็น


8
ฉันจะมอบหมายเครื่องมือเช่น bc เพื่อใส่คำตอบในตัวแปร RESULT ได้อย่างไร
Medya Gh

2
ดังนั้นคุณหมายถึงเช่น VAR = $ (echo "scale = 2; $ (($ IMG_WIDTH / $ IMG2_WIDTH))" | bc)?
Medya Gh

54
@Shevin VAR=$(echo "scale=2; $IMG_WIDTH/$IMG2_WIDTH" | bc)หรือVAR=$(bc <<<"scale=2;$IMG_WIDTH/$IMG2_WIDTH")ไม่มี $ (()) (วงเล็บคู่) ซึ่งถูกขยายโดยการทุบตีก่อนที่จะดำเนินการคำสั่ง
Nahuel Fouilleul

4
เป็นจริง แต่ awk มักจะติดตั้งในระบบอยู่แล้ว
CMCDragonkai

9
@NahuelFouilleul คุณมีคำตอบที่ดีที่สุดที่นี่ ควรเป็นคำตอบของตัวเองและยอมรับว่าเป็นคำตอบ บรรทัดนี้มีประโยชน์อย่างไม่น่าเชื่อ: VAR = $ (bc <<< "scale = 2; $ IMG_WIDTH / $ IMG2_WIDTH")
David

197

คุณสามารถทำสิ่งนี้:

bc <<< 'scale=2; 100/3'
33.33

อัปเดต 20130926 : คุณสามารถใช้:

bc -l <<< '100/3' # saves a few hits

8
... และเพิ่มตัวเลขหลายหลัก อย่างน้อยในเครื่องของฉัน yiels นี้ 33.33333333333333333333 ในขณะที่อดีตให้ 33.33
Andreas Spindler

12
@AndreasSpindler ชนิดของโพสต์เก่า แต่ในกรณีที่ทุกคนต้องการทราบสิ่งนี้สามารถเปลี่ยนแปลงได้โดยใช้คำสั่งขนาดเช่น bc -l <<< 'scale=2; 100/3'
Martie

เพียงระวังว่าคุณต้องการรับจำนวนเต็มสำหรับใช้ในภายหลังในทุบตีโดยใช้ scale = 0 ตั้งแต่ v1.06.95, bc ด้วยเหตุผลบางอย่างละเว้นตัวแปรสเกลเมื่อหมายเลขอินพุตมีส่วนทศนิยม บางทีนี่อาจจะอยู่ในเอกสาร แต่ฉันหามันไม่เจอ ลอง: echo $ (bc -l <<< 'scale = 0; 1 * 3.3333')
Greg Bell

1
@GregBell หน้าคนกล่าวUnless specifically mentioned the scale of the result is the maximum scale of the expressions involved.และมีการบันทึกพิเศษสำหรับ/ผู้ประกอบการ:The scale of the result is the value of the variable scale.
Psmith

2
ขอบคุณ @psmith ที่น่าสนใจสำหรับ / มันบอกว่า "สเกลของผลลัพธ์คือค่าของสเกลตัวแปร" แต่ไม่ใช่สำหรับการคูณ ตัวอย่างที่ดีกว่าของฉัน: bc <<< 'scale=1; 1*3.00001' สเกลคือ 5 จริง ๆ ด้วยเหตุผล bc <<< 'scale=1; 1/3.000001' สเกลคือ 1 ที่น่าสนใจหารด้วย 1 เซ็ตตรง: bc <<< 'scale=1; 1*3.00001/1'สเกลคือ 1
เกร็กเบลล์

136

ทุบตี

ตามที่ระบุไว้โดยคนอื่น ๆbashไม่สนับสนุนการคำนวณเลขทศนิยมแม้ว่าคุณสามารถปลอมมันด้วยการใช้เล่ห์เหลี่ยมทศนิยมคงที่เช่นกับทศนิยมสอง:

echo $(( 100 * 1 / 3 )) | sed 's/..$/.&/'

เอาท์พุท:

.33

ดูคำตอบของ Nilfredสำหรับแนวทางที่คล้ายกัน แต่กระชับกว่า

ทางเลือก

นอกเหนือจากที่กล่าวมาbcและawkทางเลือกนอกจากนี้ยังมีดังต่อไปนี้:

CLISP

clisp -x '(/ 1.0 3)'

ด้วยการล้างเอาต์พุต:

clisp --quiet -x '(/ 1.0 3)'

หรือผ่าน stdin:

echo '(/ 1.0 3)' | clisp --quiet | tail -n1

กระแสตรง

echo 2k 1 3 /p | dc

เครื่องคิดเลข CLI อัจฉริยะ

echo 1/3.0 | genius

Ghostscript

echo 1 3 div = | gs -dNODISPLAY -dQUIET | sed -n '1s/.*>//p' 

gnuplot

echo 'pr 1/3.' | gnuplot

JQ

echo 1/3 | jq -nf /dev/stdin

หรือ:

jq -n 1/3

ksh

echo 'print $(( 1/3. ))' | ksh

หลัว

lua -e 'print(1/3)'

หรือผ่าน stdin:

echo 'print(1/3)' | lua

แม็กซิม่า

echo '1/3,numer;' | maxima

ด้วยการล้างเอาต์พุต:

echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p'

ปม

echo 1/3 | node -p

เสียงคู่แปด

echo 1/3 | octave

Perl

echo print 1/3 | perl

python2

echo print 1/3. | python2

python3

echo 'print(1/3)' | python3

R

echo 1/3 | R --no-save

ด้วยการล้างเอาต์พุต:

echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p'

ทับทิม

echo print 1/3.0 | ruby

wcalc

echo 1/3 | wcalc

ด้วยการล้างเอาต์พุต:

echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2

zsh

echo 'print $(( 1/3. ))' | zsh

หน่วย

units 1/3

ด้วยเอาต์พุตขนาดกะทัดรัด:

units --co 1/3

แหล่งอื่น ๆ

Stéphane Chazelas ตอบคำถามแบบเดียวกันบน Unix.SX


9
คำตอบที่ดี ฉันรู้ว่ามันโพสต์ไม่กี่ปีหลังจากคำถาม แต่สมควรได้รับการตอบรับมากขึ้น
Brian Cline

2
หากคุณมี zsh อยู่ก็ควรพิจารณาที่จะเขียนสคริปต์ของคุณใน zsh แทนที่จะเป็น Bash
Andrea Corbellini


รายการที่ดี โดยเฉพาะอย่างยิ่งecho 1/3 | node -pสั้น
Johnny Wong

39

การปรับปรุงคำตอบเล็ก ๆ น้อย ๆ ของมาร์วิน:

RESULT=$(awk "BEGIN {printf \"%.2f\",${IMG_WIDTH}/${IMG2_WIDTH}}")

bc ไม่ได้มาพร้อมกับแพ็คเกจที่ติดตั้งไว้เสมอ


4
สคริปต์ awk จำเป็นต้องมีexitเพื่อป้องกันไม่ให้อ่านจากอินพุตสตรีม ฉันยังแนะนำให้ใช้-vธงของ awk เพื่อป้องกันโรคไม้จิ้มฟันที่พิงอยู่ ดังนั้น:RESULT=$(awk -v dividend="${IMG_WIDTH}" -v divisor="${IMG2_WIDTH}" 'BEGIN {printf "%.2f", dividend/divisor; exit(0)}')
aecolley

2
วิธี awkish RESULT=$(awk '{printf("result= %.2f\n",$1/$2)}' <<<" $IMG_WIDTH $IMG2_WIDTH "มากขึ้นในการทำเช่นนี้จะอ่านข้อโต้แย้งจากกระแสการป้อนข้อมูล:
jmster

1
bcเป็นส่วนหนึ่งของ POSIX โดยปกติจะถูกติดตั้งไว้ล่วงหน้า
fuz

สิ่งนี้ใช้ได้กับฉันโดยใช้ git bash ใน windows 7 ... ขอบคุณ :)
The Beast

31

คุณสามารถใช้ bc โดย-lตัวเลือก (ตัวอักษร L)

RESULT=$(echo "$IMG_WIDTH/$IMG2_WIDTH" | bc -l)

4
หากฉันไม่ได้รวม-lไว้ในระบบของฉัน bc ไม่ได้ทำคณิตศาสตร์จุดลอยตัว
starbeamrainbowlabs

28

เป็นทางเลือกแทน bc คุณสามารถใช้ awk ภายในสคริปต์ของคุณ

ตัวอย่างเช่น:

echo "$IMG_WIDTH $IMG2_WIDTH" | awk '{printf "%.2f \n", $1/$2}'

ในข้างต้น "% .2f" จะบอกให้ฟังก์ชัน printf ส่งคืนตัวเลขทศนิยมที่มีสองหลักหลังจุดทศนิยม ฉันใช้ echo ไปป์ในตัวแปรเป็นเขตข้อมูลเนื่องจาก awk ทำงานอย่างถูกต้องกับพวกเขา "$ 1" และ "$ 2" อ้างถึงอินพุตฟิลด์แรกและฟิลด์ที่สองเป็น awk

และคุณสามารถเก็บผลลัพธ์เป็นตัวแปรอื่นโดยใช้:

RESULT = `echo ...`

ยอดเยี่ยม ขอบคุณ สิ่งนี้มีประโยชน์สำหรับสภาพแวดล้อมแบบฝังที่ไม่มี bc อยู่ คุณช่วยฉันรวบรวมเวลาข้าม
กระตือรือร้น

19

มันเป็นเวลาที่เหมาะที่จะลอง zsh, (เกือบ) bash superset, พร้อมคุณสมบัติที่ดีมากมายรวมถึงคณิตศาสตร์เลขทศนิยม นี่คือตัวอย่างของคุณใน zsh:

% IMG_WIDTH=1080
% IMG2_WIDTH=640
% result=$((IMG_WIDTH*1.0/IMG2_WIDTH))
% echo $result
1.6875

โพสต์นี้อาจช่วยคุณได้: bash - ควรเปลี่ยนไปใช้ zsh เพื่อการใช้งานทั่วไป


3
ฉันเป็นแฟนตัวยงของ zsh และได้ใช้มันมา 4 ปีที่ผ่านมา แต่การใช้แบบอินเตอร์แอคทีฟเป็นสิ่งที่ดีที่นี่ สคริปต์ที่ต้องใช้ zsh มักจะไม่สามารถพกพาไปได้ในหลากหลายชุดของเครื่องจักรเนื่องจากโดยทั่วไปจะไม่ได้มาตรฐานเศร้า (เพื่อความยุติธรรมบางทีอาจไม่เป็นไร OP ไม่ได้บอกว่าจะใช้งานอย่างไร)
Brian Cline

17

ก่อนที่โฟลตจะเป็นเวลาที่ใช้ตรรกะทศนิยมคงที่:

IMG_WIDTH=100
IMG2_WIDTH=3
RESULT=$((${IMG_WIDTH}00/$IMG2_WIDTH))
echo "${RESULT:0:-2}.${RESULT: -2}"
33.33

บรรทัดสุดท้ายคือ bashim หากไม่ได้ใช้ bash ให้ลองใช้รหัสนี้แทน:

IMG_WIDTH=100
IMG2_WIDTH=3
INTEGER=$(($IMG_WIDTH/$IMG2_WIDTH))
DECIMAL=$(tail -c 3 <<< $((${IMG_WIDTH}00/$IMG2_WIDTH)))
RESULT=$INTEGER.$DECIMAL
echo $RESULT
33.33

เหตุผลหลังรหัสคือ: คูณด้วย 100 ก่อนหารเพื่อให้ได้ 2 ทศนิยม


5

หากคุณพบความแปรปรวนของการตั้งค่าของคุณคุณสามารถห่อมันลงในฟังก์ชั่น

ที่นี่ฉันห่อ bashism ลงในฟังก์ชัน div:

หนึ่งในสายการบิน:

function div { local _d=${3:-2}; local _n=0000000000; _n=${_n:0:$_d}; local _r=$(($1$_n/$2)); _r=${_r:0:-$_d}.${_r: -$_d}; echo $_r;}

หรือหลายสาย:

function div {
  local _d=${3:-2}
  local _n=0000000000
  _n=${_n:0:$_d}
  local _r=$(($1$_n/$2))
  _r=${_r:0:-$_d}.${_r: -$_d}
  echo $_r
}

ตอนนี้คุณมีฟังก์ชั่น

div <dividend> <divisor> [<precision=2>]

และใช้มันเหมือน

> div 1 2
.50

> div 273 123 5
2.21951

> x=$(div 22 7)
> echo $x
3.14

UPDATE ฉันเพิ่มสคริปต์เล็กน้อยซึ่งให้การดำเนินการพื้นฐานกับหมายเลขทศนิยมสำหรับ bash:

การใช้งาน:

> add 1.2 3.45
4.65
> sub 1000 .007
999.993
> mul 1.1 7.07
7.7770
> div 10 3
3.
> div 10 3.000
3.333

และที่นี่สคริปต์:

#!/bin/bash
__op() {
        local z=00000000000000000000000000000000
        local a1=${1%.*}
        local x1=${1//./}
        local n1=$((${#x1}-${#a1}))
        local a2=${2%.*}
        local x2=${2//./}
        local n2=$((${#x2}-${#a2}))
        local n=$n1
        if (($n1 < $n2)); then
                local n=$n2
                x1=$x1${z:0:$(($n2-$n1))}
        fi
        if (($n1 > $n2)); then
                x2=$x2${z:0:$(($n1-$n2))}
        fi
        if [ "$3" == "/" ]; then
                x1=$x1${z:0:$n}
        fi
        local r=$(($x1"$3"$x2))
        local l=$((${#r}-$n))
        if [ "$3" == "*" ]; then
                l=$(($l-$n))
        fi
        echo ${r:0:$l}.${r:$l}
}
add() { __op $1 $2 + ;}
sub() { __op $1 $2 - ;}
mul() { __op $1 $2 "*" ;}
div() { __op $1 $2 / ;}

1
local _d=${3:-2}ง่ายกว่า
KamilCuk

4

ไม่ใช่จุดลอยตัวจริงๆ แต่ถ้าคุณต้องการบางสิ่งบางอย่างที่ตั้งค่ามากกว่าหนึ่งผลลัพธ์ในการร้องขอ bc ...

source /dev/stdin <<<$(bc <<< '
d='$1'*3.1415926535897932384626433832795*2
print "d=",d,"\n"
a='$1'*'$1'*3.1415926535897932384626433832795
print "a=",a,"\n"
')

echo bc radius:$1 area:$a diameter:$d

คำนวณพื้นที่และเส้นผ่านศูนย์กลางของวงกลมที่มีรัศมีใน 1 ดอลลาร์


4

มีหลายสถานการณ์ที่คุณไม่สามารถใช้ bc ได้เพราะมันอาจไม่มีอยู่จริงเช่นใน busybox หรือระบบฝังตัวบางรุ่น ไม่ว่าในกรณีใดก็ตามการ จำกัด การพึ่งพาภายนอกเป็นสิ่งที่ดีที่จะทำเช่นนั้นคุณสามารถเพิ่มศูนย์ลงในจำนวนที่หารด้วย (ตัวเศษ) นั่นก็เท่ากับการคูณด้วยกำลัง 10 (คุณควรเลือกกำลัง 10 ตาม ความแม่นยำที่คุณต้องการ) ซึ่งจะทำให้การหารเอาท์พุทเป็นจำนวนเต็ม เมื่อคุณมีจำนวนเต็มถือว่ามันเป็นสตริงและตำแหน่งจุดทศนิยม (ย้ายจากขวาไปซ้าย) จำนวนครั้งเท่ากับพลังของสิบที่คุณคูณเศษโดย นี่เป็นวิธีง่าย ๆ ในการรับผลลัพธ์แบบลอยโดยใช้ตัวเลขจำนวนเต็มเท่านั้น


1
แม้แต่ Busybox ก็มี Awk บางทีน่าจะมีคำตอบ Awk ที่เด่นชัดกว่านี้
tripleee

4

ในขณะที่คุณไม่สามารถใช้การแบ่งจุดแบบลอยใน Bash คุณสามารถใช้การหารจุดคงที่ได้ สิ่งที่คุณต้องทำคือคูณจำนวนเต็มด้วยกำลัง 10 แล้วหารส่วนจำนวนเต็มแล้วใช้การดำเนินการแบบโมดูโลเพื่อรับส่วนที่เป็นเศษส่วน ปัดเศษตามต้องการ

#!/bin/bash

n=$1
d=$2

# because of rounding this should be 10^{i+1}
# where i is the number of decimal digits wanted
i=4
P=$((10**(i+1)))
Pn=$(($P / 10))
# here we 'fix' the decimal place, divide and round tward zero
t=$(($n * $P / $d + ($n < 0 ? -5 : 5)))
# then we print the number by dividing off the interger part and
# using the modulo operator (after removing the rounding digit) to get the factional part.
printf "%d.%0${i}d\n" $(($t / $P)) $(((t < 0 ? -t : t) / 10 % $Pn))

4

ฉันรู้ว่ามันเก่า แต่ก็ดึงดูดเกินไป ดังนั้นคำตอบคือ: คุณไม่สามารถ ... แต่คุณสามารถทำได้ ลองทำสิ่งนี้:

$IMG_WIDTH=1024
$IMG2_WIDTH=2048

$RATIO="$(( IMG_WIDTH / $IMG2_WIDTH )).$(( (IMG_WIDTH * 100 / IMG2_WIDTH) % 100 ))

เช่นเดียวกับที่คุณได้รับ 2 หลักหลังจากจุดตัด (เรียกว่าปัดเศษไปด้านล่าง, ฮ่าฮ่า) ใน bash บริสุทธิ์ (ไม่จำเป็นต้องเปิดกระบวนการอื่น ๆ ) แน่นอนถ้าคุณต้องการเพียงหนึ่งหลักหลังจากจุดที่คุณคูณด้วย 10 และทำแบบโมดูโล 10

สิ่งนี้ทำอะไร:

  • $ แรก ((... )) ทำการหารจำนวนเต็ม;
  • วินาที $ ((... )) ทำการหารจำนวนเต็มกับบางสิ่งที่ใหญ่กว่า 100 เท่าโดยหลักจะย้าย 2 หลักของคุณไปทางซ้ายของจุดจากนั้น (%) ทำให้คุณได้รับเพียง 2 หลักด้วยการทำ modulo

โบนัสแทร็ก : bc รุ่น x 1000 ใช้เวลา 1,8 วินาทีบนแล็ปท็อปของฉันในขณะที่แบชบริสุทธิ์ใช้เวลา 0,016 วินาที


3

วิธีคำนวณจุดลอยใน bash:

แทนที่จะใช้ " here strings " ( <<<) กับbcคำสั่งเหมือนหนึ่งในตัวอย่างที่ได้รับการโหวตมากที่สุดคือนี่คือbcตัวอย่างจุดลอยตัวที่ฉันโปรดปรานที่นี่จากEXAMPLESส่วนของbcman pages (ดูman bcหน้าคู่มือ)

pi = 4*atan(1)ก่อนที่เราจะเริ่มรู้ว่าสมปี่คือ: a()ด้านล่างเป็นฟังก์ชันทางคณิตศาสตร์สำหรับbcatan()

  1. นี่คือวิธีการจัดเก็บผลมาจากการคำนวณจุดลอยเข้าไปในตัวแปรทุบตี - piในกรณีนี้ลงในตัวแปรที่เรียกว่า โปรดทราบว่าscale=10ตั้งค่าจำนวนหลักทศนิยมของความแม่นยำเป็น 10 ในกรณีนี้ ใด ๆ ตัวเลขทศนิยมหลังจากที่สถานที่แห่งนี้จะถูกตัดทอน

    pi=$(echo "scale=10; 4*a(1)" | bc -l)
  2. ตอนนี้หากต้องการมีรหัสบรรทัดเดียวที่พิมพ์ค่าของตัวแปรนี้เพียงเพิ่มechoคำสั่งไปยังจุดสิ้นสุดเป็นคำสั่งติดตามผลดังนี้ บันทึกการตัดที่ทศนิยม 10 ตำแหน่งตามที่ได้รับคำสั่ง:

    pi=$(echo "scale=10; 4*a(1)" | bc -l); echo $pi
    3.1415926532
  3. สุดท้ายเรามาปัดเศษกันบ้าง ที่นี่เราจะใช้printfฟังก์ชั่นปัดเศษทศนิยม 4 ตำแหน่ง โปรดสังเกตว่ารอบนี้เพื่อ3.14159... 3.1416เนื่องจากเรากำลังปัดเศษเราไม่จำเป็นต้องใช้scale=10ในการตัดเหลือทศนิยม 10 ตำแหน่งอีกต่อไปดังนั้นเราจะลบส่วนนั้นออก นี่คือทางออกสุดท้าย:

    pi=$(printf %.4f $(echo "4*a(1)" | bc -l)); echo $pi
    3.1416

นี่เป็นอีกแอปพลิเคชั่นที่ยอดเยี่ยมและสาธิตเทคนิคดังกล่าว: การวัดและการพิมพ์

โปรดทราบว่าdt_minจะถูกปัดเศษจาก0.01666666666...เป็น0.017:

start=$SECONDS; sleep 1; end=$SECONDS; dt_sec=$(( end - start )); dt_min=$(printf %.3f $(echo "$dt_sec/60" | bc -l)); echo "dt_sec = $dt_sec; dt_min = $dt_min"
dt_sec = 1; dt_min = 0.017

ที่เกี่ยวข้อง:


1
คำตอบที่มั่นคงพร้อมตัวอย่างโดยละเอียดและใช้เคส & round โดยใช้ printf
downvoteit


2

สำหรับผู้ที่พยายามคำนวณเปอร์เซ็นต์ด้วยคำตอบที่ยอมรับ แต่สูญเสียความแม่นยำ:

หากคุณทำสิ่งนี้:

echo "scale=2; (100/180) * 180" | bc

คุณจะได้รับ99.00เท่านั้นซึ่งสูญเสียความแม่นยำ

หากคุณใช้วิธีนี้:

echo "result = (100/180) * 180; scale=2; result / 1" | bc -l

99.99ตอนนี้คุณจะได้รับ

เนื่องจากคุณกำลังปรับในขณะที่พิมพ์เท่านั้น

อ้างถึงที่นี่


1

** คณิตศาสตร์จุดปลอดภัยสำหรับการฉีดใน bash / shell **

หมายเหตุ: จุดเน้นของคำตอบนี้คือเสนอแนวคิดสำหรับโซลูชันการฉีดที่ปลอดภัยเพื่อดำเนินการทางคณิตศาสตร์ใน bash (หรือเชลล์อื่น ๆ ) แน่นอนสามารถนำมาใช้เดียวกันกับการปรับเล็กน้อยเพื่อดำเนินการประมวลผลสตริงขั้นสูง ฯลฯ

โซลูชันส่วนใหญ่ที่นำเสนอสร้างสคริปต์เล็ตขนาดเล็กโดยใช้ข้อมูลภายนอก (ตัวแปรไฟล์บรรทัดคำสั่งตัวแปรสภาพแวดล้อม) อินพุตภายนอกสามารถใช้ในการฉีดโค้ดที่เป็นอันตรายเข้าไปในเครื่องยนต์ได้

ด้านล่างเป็นการเปรียบเทียบการใช้ภาษาต่าง ๆ เพื่อทำการคำนวณทางคณิตศาสตร์ขั้นพื้นฐานโดยที่ผลลัพธ์เป็นทศนิยม มันคำนวณ A + B * 0.1 (เป็นทศนิยม)

วิธีการแก้ปัญหาทั้งหมดพยายามหลีกเลี่ยงการสร้าง scriptlets แบบไดนามิกซึ่งยากมากในการดูแลรักษาแทนที่จะใช้โปรแกรมแบบสแตติกและส่งพารามิเตอร์ไปยังตัวแปรที่กำหนด พวกเขาจะจัดการพารามิเตอร์อย่างปลอดภัยด้วยอักขระพิเศษ - ลดความเป็นไปได้ของการฉีดโค้ด ข้อยกเว้นคือ 'BC' ซึ่งไม่ได้ให้ความสะดวกด้านอินพุต / เอาต์พุต

ข้อยกเว้นคือ 'bc' ซึ่งไม่มีอินพุต / เอาต์พุตใด ๆ ข้อมูลทั้งหมดมาจากโปรแกรมใน stdin และเอาต์พุตทั้งหมดจะไปที่ stdout การคำนวณทั้งหมดกำลังดำเนินการใน sandbox ซึ่งไม่อนุญาตให้มีผลข้างเคียง (การเปิดไฟล์ ฯลฯ ) ในทางทฤษฎีแล้วการฉีดที่ปลอดภัยโดยการออกแบบ!

A=5.2
B=4.3

# Awk: Map variable into awk
# Exit 0 (or just exit) for success, non-zero for error.
#
awk -v A="$A" -v B="$B" 'BEGIN { print A + B * 0.1 ; exit 0}'

# Perl
perl -e '($A,$B) = @ARGV ; print $A + $B * 0.1' "$A" "$B"

# Python 2
python -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print a+b*0.1' "$A" "$B"

# Python 3
python3 -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print(a+b*0.1)' "$A" "$B"

# BC
bc <<< "scale=1 ; $A + $B * 0.1"

สำหรับ python3 ที่มีอาร์กิวเมนต์เอง: python3 -c 'import sys ; *a, = map(float, sys.argv[1:]) ; print(a[0] + a[1]*0.1 + a[2])' "$A" "$B""4200.0" ==> 4205.63
WiringHarness

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.