[leicht bis schwer]kontinuierliche Division

CDW

0
Mitarbeiter
Eingreicht von lone.wolf
Schwierigkeitsstufe: 2 (Mittel)

Aufgabenstellung:
Schreibe ein Programm, das die Nachkommastellen, die bei einer Division rauskommen, ab der x'ten Stelle, y Stellen lang ermittelt.

Beispiel:
113 / 35 = 3,228571428571428571428 ...

Programm:
Eingabe> prog 113 35 2 4
Ausgabe< 2857
ich denke, die Aufgabenstellung ist ersichtlich.
Habe nur die Schwierigkeitsstufe etwas anders gemacht, da es hier auf die jeweils verwendete Sprache/Bibliothek ankommt (angefangen mit dem klassischen 3 Zeiler in Python bis hin zur eigenen Float-Bibliothek in C/Assembly ;) )
oder anders gesagt:
leicht: setze die Aufgabe um
mittel: verwende dabei keine zusätzlichen Module (wer Maple & Co Verwendet, ist ein Cheater ;) )
schwer: verwende keine zusätzlichen Module + die Nachkommastellenangaben sollen auch für große Werte möglich sein (wer Maple & Co verwendet, cheatet)
 
Meine Lösung:
Code:
#include <stdio.h>
#include <stdlib.h>

int dividend,divisor;

int main(int argc, char **argv){
    int i,istart,imax;
    if(argc<5) return 0;
    dividend=atoi(argv[1]);
    divisor=atoi(argv[2]);
    if(divisor==0) return 0;
    istart=atoi(argv[3]);
    imax=istart+atoi(argv[4]);
    if(istart==0) printf("%d",dividend/divisor);
    for(i=1;i<imax;i++){
        dividend=dividend % divisor;
        if(dividend==0) break;
        dividend*=10;
        if(i>=istart && i<imax)
            printf("%d",dividend/divisor);
    }
    printf("\n");
    return 0;
}

Nicht wirklich weiterverwendbar; die Aufgabenstellung sollte aber korrekt gelöst sein. Ich hoffe es ist kein Fehler drinnen.

Ich wünsche auch noch viel Spaß beim Denken :p
mfg Thunder

PS: vorkompiliert im Anhang.
 
Bei meinen php-versionen wird davon ausgegangen dass das bcmath modul installiert/aktiviert ist.
bei normalen divisionen ohne bcmath wird leider nur bis zur 13ten nachkommastelle berechnet.
PHP:
<?php

$a = 113;
$b = 35;

$start = 1;
$length = 4;

$result = explode('.',bcdiv($a,$b,50));

echo substr($result[1],$start,$length);

?>

und noch als oneliner:

PHP:
    echo substr(substr(bcdiv($argv[1],$argv[2],50),strpos(bcdiv($argv[1],$argv[2],50),'.')+1),$argv[3],$argv[4]);
 
Zuletzt bearbeitet:
Das würde auch Kommazahlen als Eingabe akzeptieren, funktioniert aber irgendwie nicht:
Könnte man, nimmt man die Anfangs- und Endtags weg, auch als Einzeiler schreiben, ich habs nur so aufgedröselt damit ich an den Fehler komme. Ich verdächtige ja den "pos(...,',')"-Part. Mit "." anstatt "," klappt's aber auch nicht. Das Problem: Er gibt nicht ab der c-ten Zahl nach dem Komma, sondern ab der c-ten Zahl vom Anfang an aus.
Code:
function habodivide(a,b:real;c,d:integer):integer;
begin
  result := strtoint(
                     copy(
                          floattostr(
                                     a/b
                                     ),
                          pos(
                              floattostr(
                                         a/b
                                         ),
                              ','
                              )+c,
                          d
                          )
                     );

end;

Das hier funktioniert, nimmt aber nur integer-Eingaben an:
Code:
function TForm1.habodivide(a,b,c,d:integer):integer;
begin
  result := strtoint(copy(floattostr(a/b),length(inttostr(a div b))+1+c,d));
end;
 
Zuletzt bearbeitet:
Kleine, aber meiner Meinung nach, sehr schöne Lösung in Haskell.
Code:
import Data.List as L
import Data.Maybe as M

decimals :: Integer -> Integer -> String
decimals n d = let (n0,d0) = divMod n d
               in (show n0) ++ "," ++ (concatMap show $ next d0)
    where next nx | d > 0 = dx : next nx1
                  | otherwise = repeat 0
                  where (dx,nx1) = divMod (nx*10) d 

cut :: (Int,Int) -> String -> String
cut (s0,s1) xs = take s1 $ drop (idx+s0) xs
    where idx = M.fromJust $ L.elemIndex ',' xs

main :: IO ()
main = mapM_ print [cut (2,4) seq, take 25 seq]
    where seq = decimals 113 35
*Main> main
"2857"
"3,22857142857142857142857"
Gruß
Felix
 
in VB

finds zwar selber net schön, weil der eingabestring immer wieder abgeschnitten wird, aber es funktioniert ^^

Code:
Module Module1
Sub Main()
Dim eingabe, erg AsString
Dim divid, divis AsDouble
Dim x, y AsInteger
 
eingabe = Console.ReadLine()
divid = CType(eingabe.Substring(0, eingabe.IndexOf(" ")), Double)
 
eingabe = eingabe.Substring(divid.ToString.Length + 1)
divis = CType(eingabe.Substring(0, eingabe.IndexOf(" ")), Double)
 
eingabe = eingabe.Substring(divis.ToString.Length + 1)
x = CType(eingabe.Substring(0, eingabe.IndexOf(" ")), Integer)
 
eingabe = eingabe.Substring(x.ToString.Length + 1)
y = CType(eingabe.Substring(0), Integer)
 
erg = (divid / divis).ToString
 
Console.WriteLine(erg)
Console.WriteLine(erg.Substring(erg.IndexOf(",") + x, y))
Console.ReadLine()
EndSub
EndModule
 
Zuletzt bearbeitet:
Nicht schön aber selten:
Code:
public class Division {
    public static void main(String args[]) {
        if (args.length != 4) {
            System.exit(1);
        }
        
        double dividend, divisor;
        int x, y, i, start, end, komma = 0;
        String ergebnis;
        
        dividend = Double.valueOf(args[0]);
        divisor = Double.valueOf(args[1]);
        x = Integer.parseInt(args[2]);
        y = Integer.parseInt(args[3]);
        
        ergebnis = String.valueOf(dividend / divisor);
       
        while (ergebnis.charAt(komma) != '.') {
            komma++;
        }
        
        for (i = komma + x; i < komma + x + y; i++) {
            System.out.print(ergebnis.charAt(i));
        }
        
        System.out.println();
    }
}
 
Das läuft wahrscheinlich auch schon auf cheaten hinaus, da Python ja beliebig lange Zahlen erlaubt, aber so funktioniert es prinzipiell:
Code:
(n1, n2, x, y) = (113, 35, 2, 4)
print n1 * (10 ** (x + y - 1)) / n2 % (10**y)
 
Zuletzt bearbeitet:
...in php

Das Thema ist zwar schon bisschen älter, aber zum wieder bisschen reinkommen doch gut geeignet. Hier mein Code in php:
PHP:
function getNachkomma($divident, $divisor, $offset, $laenge) {
 $rest = $divident;
 $ausgabe= "";
 for($i = 0, $i <= $offset+$laenge; $i++) {
  $stelle = 0;
  while($rest - $divisor > 0) {
   $rest -= $divisor;
   $stelle++;
  }
  $rest *= 10;
  
  if($i >= $offset)
   $ausgabe = $ausgabe.$stelle;
 }
 return $ausgabe;
}

Hab hier leider grad keinen Server zum Testen, kann also sein, dass es noch Fehler hat, werd das aber, sobald ich zu Hause bin, mal testen :)
LG, Micha
 
Ich habe genau genommen sogar zwei Lösungen: eine in, im Prinzip, purem C und eine zweite in C++ Metaprogrammierung. Erstere war nur zum Überprüfen der Formel, da es in der zweiten Variante recht schwer ist einen Fehler zu finden.
Code:
using namespace std;

int main(int argc, char **argv)
{
    const unsigned int dividend = 113;
    const unsigned int divisor = 35;
    const unsigned int x = 2;
    const unsigned int y = 4;

    cout << calculateDecimals(dividend, divisor, x, y) << endl;

    cout << CalculateDecimals<dividend, divisor, x, y>::result << endl;

    return 1;
}
Code:
#ifndef BORING_H
#define BORING_H

unsigned int multiplyWithTenTimes(unsigned int number, unsigned int exponent)
{
    for (unsigned int i = 0; i < exponent; ++i)
        number *= 10;

    return number;
}

unsigned int extractAllDecimals(unsigned int dividend, unsigned int divisor, unsigned int count)
{
    return multiplyWithTenTimes(dividend, count) / divisor - multiplyWithTenTimes(dividend / divisor, count);
}

unsigned int calculateDecimals(unsigned int dividend, unsigned int divisor, unsigned int x, unsigned int y)
{
    unsigned int allDecimals = extractAllDecimals(dividend, divisor, x + y - 1);
    unsigned int tooMuchDecimals = extractAllDecimals(dividend, divisor, x - 1);

    return allDecimals - multiplyWithTenTimes(tooMuchDecimals, y);
}

#endif
Code:
#ifndef INTERESTING_H
#define INTERESTING_H

template<unsigned int dividend, unsigned int divisor>
class Divide
{
public:
    static const unsigned int result = dividend / divisor;
};

template<unsigned int minuend, unsigned int subtrahend>
class Subtract
{
public:
    static const unsigned int result = minuend - subtrahend;
};

template<unsigned int summandOne, unsigned int summandTwo>
class Add
{
public:
    static const unsigned int result = summandOne + summandTwo;
};

template<unsigned int number, unsigned int count>
class MultiplyWithTenTimes
{
public:
    static const unsigned int result = MultiplyWithTenTimes<number, Subtract<count, 1>::result>::result * 10;
};

template<unsigned int number>
class MultiplyWithTenTimes<number, 0>
{
public:
    static const unsigned int result = number;
};

template<unsigned int dividend, unsigned int divisor, unsigned int x, unsigned int y>
class CalculateDecimals
{
private:
    static const unsigned int smallShift = Subtract<x, 1>::result;
    static const unsigned int bigShift = Add<smallShift, y>::result;
    static const unsigned int dividendSmallShifted = MultiplyWithTenTimes<dividend, smallShift>::result;
    static const unsigned int dividendBigShifted = MultiplyWithTenTimes<dividend, bigShift>::result;
    static const unsigned int allDecimals = Divide<dividendBigShifted, divisor>::result;
    static const unsigned int tooMuchDecimals = Divide<dividendSmallShifted, divisor>::result;

public:
    static const unsigned int result = Subtract<allDecimals, MultiplyWithTenTimes<tooMuchDecimals, y>::result>::result;
};

#endif
Herzlich sinnlos :D
 
Arbeite mich gerade ein wenig in C rein. Hier meine Lösung:
Code:
#include <stdio.h>

int main(int argc, char **argv)
{
    int i,rest;
    rest = atoi(argv[1])%(atoi(argv[2]));

       for(i=1;i<=(atoi(argv[4]))+1;i++) {
           if(i>=atoi(argv[3]))
               printf("%d",(int)(rest*10)/(atoi(argv[2])));
           rest= (rest*10)%(atoi(argv[2]));
       }
       printf("\n");
    return 0;
}
Bin für Verbesserungsvorschläge offen...
Gruß!
 
Mir ist grad aufgefallen, dass einige von euch die Aufgabe nicht richtig gelöst haben. Ich meine damit die Lösungen mit Stringkonvertierung. Es muss ab einer beliebigen Stelle ermittelt werden können - das kann zB auch 5000 sein, was bei der Stringkonvertierung nicht funktionieren dürfte...
 
Schade das in diesem Unterforum so wenig los ist, finde es echt genial zum Programmieren lernen.
Ein paar neue Aufgaben wären aber trotzdem nicht schlecht.
Naja, ich denke mein Code entspricht wohl eher der leichten Variante der Aufgabenstellung 8)
Code:
import java.math.*;

public class KontinuierlicheDivison {

    public static void main(String[] args) {
        System.out.println("Geben Sie die erste Zahl ein:");
        double zahl1 = new java.util.Scanner(System.in).nextDouble();
        System.out.println("Geben Sie die zweite Zahl ein:");
        double zahl2 = new java.util.Scanner(System.in).nextDouble();
        BigDecimal zahl3 = new BigDecimal(zahl1/zahl2);
        System.out.println(zahl3);
        System.out.println("Geben Sie die Stelle nach dem Komma an, ab der gezählt werden soll");
        int stelle1 = new java.util.Scanner(System.in).nextInt();
        System.out.println("Geben Sie die Stelle nach dem Komma an, bis zu welcher gezählt werden soll");
        int stelle2 = new java.util.Scanner(System.in).nextInt();
        StringBuffer text = new StringBuffer();
        text.append(zahl3);
        int zaehler1 = -1, zaehler2 = 0;
        boolean zahlstarts = false, zaehler = false;
        for (int i=0; i<text.length(); i++) {
            if (text.charAt(i) == 46)
                zahlstarts = true;
            if (i == stelle2) {
                zaehler=false;
            }
            if (zahlstarts == true) {
                zaehler1++;
            if (i == stelle1)
                zaehler = true;
            }
            if (zaehler == true)
                zaehler2++;
        }
        System.out.println("Der gewünschte Bereich nach dem Komma ist " + zaehler2 + " Stellen lang");
    }
}
 
Ich weiss nicht ich bin gerade auf dem Funktionalen Trip(auch wenn Rekursion hier ein Limit sein kann):
(Da ich ja keine Libs verwenden wollte habe ich auch auf sys verzichtet.)

PHP:
print("Gebe Dividend ein:")
number1 = int(input())
print("Gebe Divisor ein:")
number2 = int(input())
print("Gebe Anzahl der Stellen hinter dem Komma an:")
resolution = int(input())

def divider(number1, number2, resolution, commaNotSet = bool(1)):
    result = list()

    if(number1 < number2):
        if(commaNotSet):
            result.append(',')
            commaNotSet = bool(0)
        number1 = number1 * 10

    rest = number1 % number2
    divisionResult = int((number1-rest) / number2)
    result.append(divisionResult)

    if (rest != 0) and (resolution > 0):
        result.extend(divider(rest, number2, resolution - 1, commaNotSet))

    return result

print("".join(map(str,divider(number1, number2, resolution))))
 
Zurück
Oben