मैं एक शेल स्क्रिप्ट में दो फ्लोटिंग पॉइंट नंबरों की तुलना करना चाहता हूं। निम्नलिखित कोड काम नहीं कर रहा है:
#!/bin/bash
min=12.45
val=10.35
if (( $val < $min )) ; then
min=$val
fi
echo $min
मैं एक शेल स्क्रिप्ट में दो फ्लोटिंग पॉइंट नंबरों की तुलना करना चाहता हूं। निम्नलिखित कोड काम नहीं कर रहा है:
#!/bin/bash
min=12.45
val=10.35
if (( $val < $min )) ; then
min=$val
fi
echo $min
जवाबों:
आप पूर्णांक और आंशिक भागों को अलग से देख सकते हैं:
#!/bin/bash
min=12.45
val=12.35
if (( ${val%%.*} < ${min%%.*} || ( ${val%%.*} == ${min%%.*} && ${val##*.} < ${min##*.} ) )) ; then
min=$val
fi
echo $min
जैसा कि टिप्पणी में फ़्रेड कहता है, यह तभी काम करता है जब दोनों नंबरों में आंशिक भाग हों और दोनों भागों में समान संख्या में अंक हों। यहाँ एक संस्करण है जो पूर्णांक या आंशिक और किसी भी बैश ऑपरेटर के लिए काम करता है:
#!/bin/bash
shopt -s extglob
fcomp() {
local oldIFS="$IFS" op=$2 x y digitx digity
IFS='.' x=( ${1##+([0]|[-]|[+])}) y=( ${3##+([0]|[-]|[+])}) IFS="$oldIFS"
while [[ "${x[1]}${y[1]}" =~ [^0] ]]; do
digitx=${x[1]:0:1} digity=${y[1]:0:1}
(( x[0] = x[0] * 10 + ${digitx:-0} , y[0] = y[0] * 10 + ${digity:-0} ))
x[1]=${x[1]:1} y[1]=${y[1]:1}
done
[[ ${1:0:1} == '-' ]] && (( x[0] *= -1 ))
[[ ${3:0:1} == '-' ]] && (( y[0] *= -1 ))
(( ${x:-0} $op ${y:-0} ))
}
for op in '==' '!=' '>' '<' '<=' '>='; do
fcomp $1 $op $2 && echo "$1 $op $2"
done
1.00000000000000000000000001
इससे अधिक है 2
।
बैश फ्लोटिंग पॉइंट अंकगणित को नहीं समझता है। यह एक दशमलव बिंदु वाले संख्याओं को तार के रूप में मानता है।
इसके बजाय awk या bc का उपयोग करें।
#!/bin/bash
min=12.45
val=10.35
if [ 1 -eq "$(echo "${val} < ${min}" | bc)" ]
then
min=${val}
fi
echo "$min"
यदि आप बहुत सारे गणित संचालन करने का इरादा रखते हैं, तो संभवतः अजगर या पर्ल पर भरोसा करना बेहतर है।
आप सरल जोड़तोड़ के लिए पैकेज संख्या-बर्तन का उपयोग कर सकते हैं ...
अधिक गंभीर गणित के लिए, इस लिंक को देखें ... यह कई विकल्पों का वर्णन करता है, जैसे।
का एक उदाहरण numprocess
echo "123.456" | numprocess /+33.267,%2.33777/
# 67.0395291239087
A programs for dealing with numbers from the command line
The 'num-utils' are a set of programs for dealing with numbers from the
Unix command line. Much like the other Unix command line utilities like
grep, awk, sort, cut, etc. these utilities work on data from both
standard in and data from files.
Includes these programs:
* numaverage: A program for calculating the average of numbers.
* numbound: Finds the boundary numbers (min and max) of input.
* numinterval: Shows the numeric intervals between each number in a sequence.
* numnormalize: Normalizes a set of numbers between 0 and 1 by default.
* numgrep: Like normal grep, but for sets of numbers.
* numprocess: Do mathematical operations on numbers.
* numsum: Add up all the numbers.
* numrandom: Generate a random number from a given expression.
* numrange: Generate a set of numbers in a range expression.
* numround: Round each number according to its value.
यहाँ एक bash
हैक है ... यह एक स्ट्रिंग को बाएं से दाएं तुलना को सार्थक बनाने के लिए पूर्णांक में अग्रणी 0 जोड़ता है। कोड के इस विशेष टुकड़े के लिए आवश्यक है कि दोनों मिनट और वैल में वास्तव में दशमलव बिंदु हो और कम से कम एक दशमलव अंक हो।
min=12.45
val=10.35
MIN=0; VAL=1 # named array indexes, for clarity
IFS=.; tmp=($min $val); unset IFS
tmp=($(printf -- "%09d.%s\n" ${tmp[@]}))
[[ ${tmp[VAL]} < ${tmp[MIN]} ]] && min=$val
echo min=$min
उत्पादन:
min=10.35
फ्लोटिंग पॉइंट नंबरों (+ - * / और तुलना) पर सरल गणना के लिए, आप awk का उपयोग कर सकते हैं।
min=$(echo 12.45 10.35 | awk '{if ($1 < $2) print $1; else print $2}')
या, यदि आपके पास ksh93 या zsh (बैश नहीं) है, तो आप अपने शेल के बिल्ट-इन अंकगणित का उपयोग कर सकते हैं, जो फ्लोटिंग पॉइंट नंबरों का समर्थन करता है।
if ((min>val)); then ((val=min)); fi
अधिक उन्नत फ्लोटिंग पॉइंट गणना के लिए, ई.पू. देखें । यह वास्तव में मनमाने ढंग से सटीक निर्धारण संख्या पर काम करता है।
संख्याओं की तालिकाओं पर काम करने के लिए, R ( उदाहरण ) देखें।
कमांड sort
में एक विकल्प -g
( --general-numeric-sort
) होता है, जिसका उपयोग न्यूनतम या अधिकतम खोज कर <
, "कम से कम" या >
"से बड़ा" के रूप में किया जा सकता है ।
ये उदाहरण न्यूनतम पा रहे हैं:
$ printf '12.45\n10.35\n' | sort -g | head -1
10.35
यह ई-संकेतन के साथ फ्लोटिंग पॉइंट नंबरों के सामान्य सामान्य अंकन के साथ काम करता है
$ printf '12.45E-10\n10.35\n' | sort -g | head -1
12.45E-10
ध्यान दें , वास्तव में से कम, E-10
पहली संख्या बना रही 0.000000001245
है 10.35
।
अस्थायी बिंदु मानक, IEEE754 , कुछ विशेष मूल्यों को परिभाषित करता है। इन तुलनाओं के लिए, दिलचस्प INF
अनंत के लिए हैं। नकारात्मक अनंतता भी है; दोनों मानक में अच्छी तरह से परिभाषित मूल्य हैं।
$ printf 'INF\n10.35\n' | sort -g | head -1
10.35
$ printf '-INF\n10.35\n' | sort -g | head -1
-INF
के sort -gr
बजाय अधिकतम उपयोग खोजने के लिए sort -g
, क्रम को उलट कर:
$ printf '12.45\n10.35\n' | sort -gr | head -1
12.45
<
तुलना करने के लिए ("कम से कम") को लागू करने के लिए , इसलिए इसका उपयोग if
आदि में किया जा सकता है , न्यूनतम मूल्यों में से एक से तुलना करें। यदि पाठ की तुलना में न्यूनतम मान के बराबर है , तो यह अन्य मूल्य से कम है:
$ a=12.45; b=10.35
$ [ "$a" = "$(printf "$a\n$b\n" | sort -g | head -1)" ]
$ echo $?
1
$ a=12.45; b=100.35
$ [ "$a" = "$(printf "$a\n$b\n" | sort -g | head -1)" ]
$ echo $?
0
a == min(a, b)
करना उसी के समान है a <= b
। यह ध्यान देने योग्य है कि यह कड़ाई से कम के लिए जाँच नहीं करता है। यदि आप ऐसा करना चाहते हैं, तो आपको a == min(a, b) && a != max(a, b)
अन्य पासवर्डa <= b and not a >= b
बस का उपयोग करें ksh
( ksh93
ठीक) या zsh
, जो दोनों मूल रूप से फ्लोटिंग पॉइंट अंकगणित का समर्थन करते हैं:
$ cat test.ksh
#!/bin/ksh
min=12.45
val=10.35
if (( $val < $min )) ; then
min=$val
fi
echo "$min"
$ ./test.ksh
10.35
संपादित करें: क्षमा करें, मुझे याद है ksh93
कि पहले से ही सुझाव दिया गया था। मेरा जवाब सिर्फ यह रखने के लिए कि प्रारंभिक प्रश्न में पोस्ट की गई स्क्रिप्ट को खोल स्विच के बाहर कोई बदलाव नहीं किया जा सकता है।
Edit2: ध्यान दें कि ksh93
वैरिएबल कंटेंट को आपके लोकेल के साथ संगत होना चाहिए, यानी फ्रेंच लोकेल के साथ, डॉट के बजाय कॉमा का उपयोग किया जाना चाहिए:
...
min=12,45
val=10,35
...
एक और अधिक मजबूत समाधान स्क्रिप्ट की शुरुआत में लोकेल सेट करना है, यह सुनिश्चित करने के लिए कि यह उपयोगकर्ता के लोकेल की परवाह किए बिना काम करेगा:
...
export LC_ALL=C
min=12.45
val=10.35
...
.
(इसलिए आधी दुनिया में जहाँ दशमलव विभाजक नहीं है ,
)। zsh
यह मुद्दा नहीं है।
LC_ALL
, तो LC_NUMERIC काम नहीं करेगा , इसका मतलब यह भी है कि नंबर उपयोगकर्ता के पसंदीदा प्रारूप में प्रदर्शित नहीं होंगे (या इनपुट)। संभावित बेहतर दृष्टिकोण के लिए unix.stackexchange.com/questions/87745/what-does-lc-all-c-do/… देखें ।
.
वैसे भी है।
min=$(echo "${min}sa ${val}d la <a p" | dc)
का उपयोग करता है dc
करने के लिए कैलकुलेटर s
के लिए मूल्य फाड़े $min
रजिस्टर में a
और d
का मूल्य uplicates $val
अपने मुख्य निष्पादन ढेर के शीर्ष पर। इसके बाद स्टैक के शीर्ष पर l
सामग्री होती है a
, जिस बिंदु पर यह दिखता है:
${min} ${val} ${val}
<
ढेर के बंद शीर्ष दो प्रविष्टियों पॉप और उन्हें तुलना करती है। तो स्टैक तब दिखता है:
${val}
यदि शीर्ष प्रविष्टि दूसरे से शीर्ष पर कम थी तो यह शीर्ष a
पर की सामग्री को धक्का देता है , इसलिए स्टैक ऐसा दिखता है:
${min} ${val}
इसके अलावा यह कुछ भी नहीं करता है और स्टैक अभी भी दिखता है:
${val}
फिर यह सिर्फ p
शीर्ष स्टैक प्रविष्टि पर हस्ताक्षर करता है।
तो आपकी समस्या के लिए:
min=12.45
val=12.35
echo "${min}sa ${val}d la <a p" | dc
###OUTPUT
12.35
परंतु:
min=12.45
val=12.55
echo "${min}sa ${val}d la <a p" | dc
###OUTPUT
12.45
पुराने, अच्छे का उपयोग क्यों न करें expr
?
उदाहरण वाक्य रचना:
if expr 1.09 '>' 1.1 1>/dev/null; then
echo 'not greater'
fi
के लिए सही अभिव्यक्ति, expr बाहर निकलें कोड 0 है, स्ट्रिंग '1' stdout करने के लिए भेजा है। झूठे भावों के लिए उलटा ।
मैंने जीएनयू और फ्रीबीएसडी 8 एक्सपायर के साथ इसकी जांच की है।
expr 1.09 '<' -1.1
प्रिंट 1
और बाहर निकलेगा 0
।
यह जांचने के लिए कि क्या दो (संभवतः आंशिक) क्रम में हैं, sort
(यथोचित) पोर्टेबल:
min=12.45
val=12.55
if { echo $min ; echo $val ; } | sort -n -c 2>/dev/null
then
echo min is smallest
else
echo val is smallest
fi
हालाँकि, यदि आप वास्तव में न्यूनतम मूल्य को अपडेट रखना चाहते हैं, तो आपको इसकी आवश्यकता नहीं है if
। संख्याओं को क्रमबद्ध करें, और हमेशा पहले (कम से कम) एक का उपयोग करें:
min=12.45
val=12.55
smallest=$({ echo $min ; echo $val ; } | sort -n | head -n 1)
echo $smallest
min=$smallest
आमतौर पर मैं एम्बेडेड पायथन कोड के साथ ऐसी ही चीजें करता हूं:
#!/bin/sh
min=12.45
val=10.35
python - $min $val<<EOF
if ($min > $val):
print $min
else:
print $val
EOF
$ min=12.45
$ val=10.35
$ [ "$min" \< "$val" ] && echo $val || echo $min
$ 12.45
$ val=13
$ [ "$min" \< "$val" ] && echo $val || echo $min
$ 13
0.5
और प्रयास करें0.06
)। आप बेहतर ढंग से एक उपकरण का उपयोग करेंगे जो पहले से ही दशमलव संकेतन को समझता है।