2017-11-12 2 views
4

Ich versuche, dies in Bash zu tun:Wie führe ich diese Berechnung durch und gebe sie auf Standard aus?

read n 

echo int(math.ceil((math.sqrt(1 + 8 * n) - 1)/2)) 

Natürlich ist diese Syntax nicht funktioniert, aber ich bin setze es einfach da, so kann man sagen, was ich zu tun versuchen.

Gibt es eine einfache Möglichkeit, dies tatsächlich in gültige Bash zu machen?

+1

Es gibt sicherlich kein 'sqrt' Operator in' bash'. –

+0

Muss ich meine eigene sqrt-Funktion schreiben? – user8926565

+0

Nicht sicher ob es hilft, aber da '(8n + 1)' ungerade ist, dann wenn 'sqrt (8n + 1) 'ein ganzzahliger Wert ist, muss es auch ungerade sein. Folglich ist das Subtrahieren von (1) und das Dividieren durch (2) immer ganzzahlig. Wenn also "(n)" für jede ganze Zahl "(k)" als "k (k + 1)/2" ausgedrückt werden kann, dann ist das Ergebnis eine ganze Zahl. Andernfalls füge eins zum ganzzahligen Teil hinzu. –

Antwort

2

Obwohl Sie bitten, dies in Bash zu tun, gibt es keine native Unterstützung für Funktionen wie Quadratwurzel oder Decke. Es wäre einfacher, zu Perl zu delegieren:

perl -wmPOSIX -e "print POSIX::ceil((sqrt(1 + 8 * $n) - 1)/2)" 

Alternativ können Sie bc verwenden, um die Quadratwurzel zu berechnen, und einige Bash die Decke zu berechnen.

Lassen Sie uns eine Funktion definieren, die das Ergebnis der Formel druckt mit sqrt von bc:

formula() { 
    local n=$1 
    bc -l <<< "(sqrt(1 + 8 * $n) - 1)/2" 
} 

Die -l Flagge ändert die scale von der Standard 0 bis 20. Dies wirkt sich auf die Skala in der Anzeige des Schwebens Punkt Ergebnisse. Zum Beispiel mit der Standard-Null würde 10/3 nur drucken 3. Wir müssen die Floating-Point-Details im nächsten Schritt die Decke zu berechnen.

ceil() { 
    local n=$1 
    local intpart=${n%%.*} 
    if [[ $n =~ \.00*$ ]]; then 
     echo $intpart 
    else 
     echo $((intpart + 1)) 
    fi 
} 

Die Idee dabei ist, den ganzzahligen Teil zu extrahieren, und wenn der Dezimalteil alle Nullen, dann drucken wir einfach den ganzzahligen Teil, sonst der ganzzahlige Teil + 1, so dass die Obergrenze ist.

Und eine letzte einfache Funktion, die die oben genannten Funktionen kombiniert das Ergebnis zu erhalten, die Sie wollen:

compute() { 
    local n=$1 
    ceil $(formula $n) 
} 

Und einen Kontrolleur Funktion testen:

check() { 
    local n num 
    for n; do 
     num=$(formula $n) 
     echo $n $num $(compute $n) 
    done 
} 

Lassen Sie uns es versuchen:

check 1 2 3 4 7 11 12 16 17 

Es produziert:

1 1.00000000000000000000 1 
2 1.56155281280883027491 2 
3 2.00000000000000000000 2 
4 2.37228132326901432992 3 
7 3.27491721763537484861 4 
11 4.21699056602830190566 5 
12 4.42442890089805236087 5 
16 5.17890834580027361089 6 
17 5.35234995535981255455 6 
1

Sie können bc 's sqrt Funktion verwenden.

echo "(sqrt(1 + 8 * 3) - 1)/2" | bc 

Ceil Funktion kann unter Verwendung der Verfahren in dieser Antwort beschrieben umgesetzt.

Getting Ceil integer

Für zB:

ceiling_divide() { 
     ceiling_result=`echo "($1 + $2 - 1)/$2" | bc` 
    } 
+0

Wenn ich richtig umgesetzt habe, was Sie geschrieben haben, scheitert Ihre Formel für Werte von n wie 4, 7, 11, 12, 16, 17 ... –

1

Sie können bc für die ganze Arbeit verwenden

$>cat filebc 

print "Enter a number\n"; 
scale=20 
a=read() 
b=((sqrt(1 + 8 * a) - 1)/2) 
scale=0 
print "ceil = "; 
((b/1)+((b%1)>0)) 
quit 

Nennen Sie es, wie die

bc -q filebc 
Verwandte Themen