Zum Inhalt springen

DITTY

Mitglieder
  • Gesamte Inhalte

    109
  • Benutzer seit

  • Letzter Besuch

Letzte Besucher des Profils

Der "Letzte Profil-Besucher"-Block ist deaktiviert und wird anderen Benutzern nicht angezeit.

  1. Hallo Zusammen, ich habe eine Reihe von jUnit 4-Tests (@RunWith(JUnitPlatform.class)) und neuerdings u.a. auch erste einfache jUnit 5-Tests. Einzeln lassen sich auch alle erfolgreich ausführen. Nun möchte ich mir gerne aus meinen Testklassen einzelne Test Suiten zusammenstellen: Hierzu eine jUnit 5-Test-Suite (die aber auch die bisherigen jUnit 4-Testklassen ausführen können sollte): package TestSuite.Dummy; import org.junit.platform.runner.JUnitPlatform; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.SelectPackages; import org.junit.platform.suite.api.SuiteDisplayName; import org.junit.runner.RunWith; import Main.Demo.*; @RunWith(JUnitPlatform.class) @SuiteDisplayName("JUnit 4+5 Suite Demos") @IncludeEngines({"junit-jupiter", "junit-vintage"}) @SelectPackages({"Main.Demo"}) @SelectClasses({ T5.class, T4.class, T2.class, T3.class, T1.class }) public class AllTests { } Hierzu eine jUnit 4-TestSuite (die auch jUnit 5-Tests ausführen können sollte): package TestSuite.Dummy; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; import Main.Demo.T1; import Main.Demo.T2; import Main.Demo.T3; import Main.Demo.T4; import Main.Demo.T5; @RunWith(Suite.class) //@RunWith(JUnitPlatform.class) @SuiteClasses({ T2.class, T1.class, T3.class, T4.class, T5.class }) public class TestSuite_Dummy_01 { } Problem ist nun, dass ich mit meinem Eclipse 4.7.2 (Oxygen.2 mit Java 9.0.4 und jUnit 5) es einfach nicht hinkriege, dass die jUnit 5-Tests im jUnit 5-Modus (Eclipse: Rechtsklick > Run As > RunConfigurations... > Test runner: JUnit 5) ausgeführt werden: Weder die obige jUnit 5-TestSuite als auch die untere jUnit 4-TestSuite führen unter Angabe des JUnitPlatform.class-Runners (im Quellcode die Annotation @RunWith) über die TestSuite keine Tests aus. Die jUnit 5-TestSuite findet laut Fehlermeldung "keine jUnit 5-Tests" (T4, T5) und auch die vorhandenen jUnit 4-Tests (T1, T2, T3) werden nicht mit ausgeführt: Das gleiche Verhalten zeigt sich auch bei der jUnit 4-TestSuite, wenn ich via @RunWith-Annotation den JUnitPlatform.class angebe (anstatt den Suite.class-Runner). Erst, wenn ich den jUnit 4-Modus (Eclipse: Rechtsklick > Run As > RunConfigurations... > Test runner: JUnit 4) einstelle und den Suite.class-Runner im Quelltext verwende, führt zumindest die jUnit 4-TestSuite sowohl die jUnit 4- als auch die jUnit 5-Testklassen aus: Bei der jUnit 5-TestSuite regt sich hingegen nichts bzw. er führt zwar den Test Run der TestSuite aus, aber keinerlei jUnit 4- und 5-Tests: Nun zu meinen Fragen/Problemen, wo ich Euch um Rat / Hilfe oder gar Lösungsvorschläge bitten möchte, da ich hier leider nicht weiter weiß: 1.) Es muss doch möglich sein, alles - jedoch insb. jUnit 5-Tests - im jUnit 5-Modus (Eclipse: Rechtsklick > Run As > RunConfigurations... > Test runner: JUnit 5) ausführen zu lassen? Für jUnit 4-Tests kommt schließlich junit-vintage und JUnitPlatform.class-Runner zum Einsatz, ansonsten jUnit Jupiter für die 5er. Was mache ich falsch? Im Internet finde ich leider nichts passendes. Gerne möchte ich von den jUnit 4-TestSuites weg. Aktuell scheint diese jedoch die einzige zu sein, die alles korrekt ausführt, wenn ich im jUnit 4-Modus ausführen lasse. Aber wie gesagt, mein Ziel sollen reine jUnit 5-TestSuites mit dem JUnitPlatform.class-Runner und den neuen Annotationen (@SuiteDisplayName, @IncludeEngines, @SelectPackages, @SelectClasses) wie oben zu sehen sein und nicht die alten jUnit 4-TestSuites. Ebenso möchte ich alle meine jUnit 4-Testklassen zu jUnit 5 migrieren. Aus meiner Sicht machen dann Runs im jUnit 4-Modus einfach keinen Sinn mehr. 2.) Gemeinsame Daten zwischen den Testklassen: Aktuell missbrauche ich aufgrund der nicht funktionierenden TestSuiten klassische jUnit 5-Tests als TestSuite-Container, mit deren Hilfe ich die anderen Testklassen bzw. der darin befindlichen Test-Funktionen ausführen lasse. Konkret geht es um SeleniumRC-Tests. Hierzu habe ich eine eigene Klasse geschrieben, die mir meine komplette Testumgebung erstellt, inkl. erzeugen des WebDrivers. Bisher musste ich in jeder Testklasse ein eigenes Objekt (QAE) dieser Klasse erzeugen lassen. Dadurch kann ich zwar Browsertests erfolgreich ausführen, die jedoch voneinander unabhängig laufen, weil jede Testklasse ein eigenes QAE-Objekt instanziiert. Strukturell ist meine Testklassen-Hierarchie jedoch so nicht gedacht und auch möchte ich nicht immer für jeden zu testenden Use Case alle möglichen Testfunktionen aus einer Testklasse ausführen lassen (z.B. für einen Checkout-Test - Testklasse: Bestellung - im eingeloggten Zustand, ohne die MyAccount-Seiten - zugehörig zu meiner Testklasse: Login - mit testen zu müssen). Gibt es Möglichkeiten, dass sich mehrere Testklassen bei jedem Run ein gemeinsames (QAE)-Objekt teilen? Und ist es möglich, dass sich Testklassen einander Daten austauschen (kommunizieren) können? Wenn ja (jeweils), wie? 3.) Interaktions- und / oder Steuerungsmöglichkeiten in TestSuites: Kann man bei klassischen TestSuites wie oben Daten / Objekte an die aufzurufenden Testklassen übergeben? Dies würde zumindest 2.) lösen, wenn die TestSuites denn funktionieren würden. Aber angenommen sie funktionieren irgendwann mal, wenn ja, wie kann ich in einer TestSuite Objekte an Testklassen überreichen? Und kann man auch steuernd in den Run einer TestSuite eingreifen? Bisher gebe ich in der Testsuite nur die Testklassen an, die nacheinander abgearbeitet werden sollen. Ich würde gerne bestimmte Testklassen und sogar einzelne Funktionen daraus vom weiteren Testrun JIT ausschließen wollen, wenn eine bestimmte vorhergehende Testklasse bzw. einzelne Testfunktion fehlschlug. Habt besten Dank schonmal im Voraus für Eure Hilfen. VG DITTY
  2. Hallo Zusammen, ich bin derzeit dabei mich in jUnit 5 einzuarbeiten (mit Migrationsprojekten von jUnit 4 zu jUnit 5). Leider stoße ich derzeit an ein paar Grenzen meiner Kenntnisse. Konkret geht es um die nachfolgend genannten Dinge. Für Lösungen verwende ich u.a. diese Seite hier: https://howtoprogram.xyz/2016/10/28/junit-5-parameter-resolution-example/ (natürlich auch noch andere: z.B. https://junit.org/junit5/docs/current/user-guide/) Ich möchte gerne einfache Non-Parameterized- als auch Parameterized jUnit 5-Tests ausführen lassen, wo ich als Testfunktionsparameter jedoch keine Standarddatentypen (primitive, String, ENUMs, etc.) an die Testinstanzen übergebe, sondern Objekte eines eigenen Datentyps (ClientDescription). ClientDescription ist wie folgt definiert: package ISHQA.StdLibCore; public class ClientDescription { public String ...; public String ...; public String ...; public String ...; public String ...; public String ...; public String ...; public ClientDescription() { } public ClientDescription(String, String, String, String, String, String, String) { ... } } Hierzu habe ich für meine Klasse einen ParameterResolver (Parameter Resolution by type) geschrieben: package ISHQA.StdLibCore.jUnit; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import ISHQA.StdLibCore.ClientDescription; public class ClientDescriptionParameterResolver implements ParameterResolver { @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return new ClientDescription(); } @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return (parameterContext.getParameter().getType() == ClientDescription.class); } } Damit funktioniert hier schonmal dieser nicht parametrisierte Test (test02(ClientDescription)): TestClass01.java: ================================================================== package Main.Demo; import ISHQA.StdLibCore.ClientDescription; import ISHQA.StdLibCore.jUnit.*; @RunWith(JUnitPlatform.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @ExtendWith(ClientDescriptionParameterResolver.class) @DisplayName("Test cases") public class TestClass01 { //... @Test public void test02(ClientDescription client) { //...client... } //... } Nun bräuchte ich Rat / Hilfe beim Implementieren für folgende weiteren Dinge: 1.) Ich möchte das obige Beispiel gerne auf die gleiche Weise für parametrisierte Tests ausführen lassen, analog zum Beispiel für Strings: TestClass01.java: ================================================================== //... @DisplayName("Test Case 01") @ParameterizedTest(name = "{index} with [{arguments}]") @ValueSource(strings = { "'EAH','Prod','LIVE','DE','de'" }) public void test01(String testData) throws Exception { //...using testData... } //... Ich möchte gerne bei @ValueSource Objekte meines eigenen Datentyps angeben wollen, die übergeben werden sollen. Nur wie ist die Notation hierfür? Strings und Zahlen sind mir klar (siehe Beispiel), aber wie bei Klassenobjekten??? Und muss die ClientDescriptionParameterResolver-Klasse dazu noch angepasst werden? 2.) Ich möchte gerne den ClientDescriptionParameterResolver dahingehend anpassen, dass er mit beiden Konstruktoren von ClientDescription zurecht kommt, also wahlweise beide ausführen kann. Aktuell führt der ClientDescriptionParameterResolver nur den Standardkonstruktor von "ClientDescription()" aus, sodass jeder Testrun stets ein neu instantiiertes Objekt erhält. Im Hintergrund habe ich eine hardcodierte "Datenbank" mit mehreren Objekten vom Typ ClientDescription, die ich gerne für einzelne Testruns übergeben möchte. Muss ich hierfür den ClientDescriptionParameterResolver entsprechend abändern? 3.) Nach der Dokumentation kann man Parameter nach Name, Typ (wie oben schon implementiert), Annotation oder Kombinationen von diesen resolven. Analog zur Implementierung "Parameter Resolution by type" habe ich noch eine für "Parameter Resolution by annotation" versucht umzusetzen: ClientDescriptionAnnotationParameterResolver.java: ================================================================== package ISHQA.StdLibCore.jUnit; import java.lang.annotation.Annotation; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.platform.commons.util.ReflectionUtils; public class ClientDescriptionAnnotationParameterResolver implements ParameterResolver { @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return ReflectionUtils.newInstance(parameterContext.getParameter().getType()); } @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return parameterContext.getParameter().isAnnotationPresent(ClientDescriptionParam.class); } } ClientDescriptionParam.java: ================================================================== package ISHQA.StdLibCore.jUnit; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface ClientDescriptionParam { } , sodass Folgendes dann möglich wird: TestClass02.java: ================================================================== package Main.Demo; import ISHQA.StdLibCore.ClientDescription; import ISHQA.StdLibCore.jUnit.*; @RunWith(JUnitPlatform.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @ExtendWith(ClientDescriptionAnnotationParameterResolver.class) @DisplayName("Test cases") public class TestClass02 { //... @Test public void test03(@ClientDescriptionParam ClientDescription client) { //... } //... } oder bzgl. der Parameter in Kombination alle Möglichkeiten zusammen: TestClass03.java: ================================================================== package Main.Demo; import ISHQA.StdLibCore.ClientDescription; import ISHQA.StdLibCore.jUnit.*; @RunWith(JUnitPlatform.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @ExtendWith(ClientDescriptionParameterResolver.class) @DisplayName("Test cases") public class TestClass03 { //... @Test public void test02(ClientDescription client) { } @Test public void test03(@ClientDescriptionParam ClientDescription client) { } @ClientDescriptionParam @Test public void test04(ClientDescription client) { } @ClientDescriptionParam @Test public void test05(@ClientDescriptionParam ClientDescription client) { } //... } Auch hier analog zu 1.) und 2.) die Frage, was ich wo und wie anpassen muss, damit a.) meine eigene Annotation "@ClientDescriptionParam" auch bei @ParameterizedTest-Tests verwendbar wird, nicht nur bei @Test-Tests. Habt schonmal besten Dank im Voraus für Eure Hilfen. VG DITTY
  3. Ja genau das wollte ich ja eben nicht machen. Ich möchte keine neue oder eine bestehend Programmiersprache (nach)bauen, auch keinen eigenen neuen Compiler. Ich spiele mit dem Gedanken, einem C/C++-Compiler mit den Möglichkeiten von C/C++ andere Programmiersprachen beizubringen. Mein erster Gedanke zielt in die Richtung von #defines / Präprozessor-/Compilerdirektiven, typedefs, structs und class´s. Pascal lässt sich z.B. größtenteils in C/C++ abbilden, nur eben bislang nicht alles bzw. gemäß meiner obigen Fragen weiß ich nicht, wie ich gewisse Dinge realisieren könnte. Es ist von mir explizit gewollt, dass am Ende ruhig wieder C/C++-Code herauskommt der zu einem Exec. übersetzt wird. Ich würde nur gerne andere Programmiersprachen in C/C++ direkt inline nutzen können, so wie bei CUDA-C, extern "C" in C++ und Inline-Assembler. Ähnliches ist bereits bei den Embarcadero-Produkten möglich, wo sich C/C++, Delphi/Pascal/Objective-Pascal und Assembler wild mischen lassen. Aber dies ist denke ich stark Compiler-implementiert, doch ich bin nicht daran interssiert, einen neuen, eigenen Compiler zu bauen, sondern C/C++ mit seinen gegebenen Mitteln entsprechend zu erweitern. Ich stelle gerade fest, dass GCC doch mit LLVM, Clang und CIL zusammenarbeiten kann. Ich werde wohl beide Lösungsansätze weiterverfolgen. Deshalb würde ich in diesem Thread meinen ersten Lösungsversuch mittels den gegebenen Mitteln von C/C++ (defines, Präprozessor-/Compilerdirektiven, typedefs, structs, class´s) angehen wollen (und LLVM, CIL seperat). Deshalb wäre ich sehr dankbar für Hinweise, Tipps, Tricks, vlt. gar schon Lösungen oder Lösungsansätze für meine obigen zwei Hauptfragen, sowie zahlreichen Teilfragen. MfG DITTY :-)
  4. Sers COM, ich habe ein interessantes Vorhaben und habe dazu ein paar Fragen: 1.) Pseudosprachen mit C/C++ bauen: Ich würde gerne ein paar Programmiersprachen nachbauen, zumindest grob. Z.B. Pascal. Solange es um Bezeichner geht, ist das kein Problem, etwa: #define writeln printf( #define BEGIN { #define END }; Aber wie bringe ich C/C++ quasi folgendes bei: #define := = Ich suche also nach einer Möglichkeit, auch Sonderzeichen und Zeichenketten als Quellcode neu zu definieren: #define "DO i = 1, 4711 {...} ENDDO" "for(i=1;i<=4711;++i){{...}}" Ebenso würde ich gerne den Basisdatentyp int zu einem Klassendatentyp redefinieren, z.B.: struct|class INT { public: int var; }; #define int INT() Grund ist der, dass ich auch unter C++ wie in C# bei int ein Klassenobjekt instanzieren möchte, welches ich dann später z.B. um weitere Funktionen ergänzen könnte. 2.) Multicompilierung: Gibt es auch sowas wie "extern "C"" bei C++ auch für andere Programmiersprachen? Etwa: extern "g95" extern "Pascal" extern "C#" etc.? Kann man sowas selber implementieren oder ist das ein Feature, was der Compiler implementiert haben muss? Ich möchte nämlich gerne programmiersprachenübergreifend mit C/C++ arbeiten, also auch mal Pascal-Code ohne manuelle Portierung und Wrapper INLINE in C/C++-Projekten verwenden. Ich denke, dass hierfür die GCC sehr gut geeignet ist, da jeder GCC-Compiler letztendlich das selbe Code-Backend verwendet, ähnlich wie bei den .NET-Sprachen und LLVM, also eine Art universelle Zwischensprache. So kann ich z.B. ganz komfortabel mit dem gcc oder auch g++, Fortran-Dateien mit übersetzen und linken lassen, da sowohl der gcc-, g++-, als auch der gfortran--Compiler binärkompatiblen OBJ-Code erzeugen und anschließend linken. Hierfür muss ich aber immer im C++-Code Wrapper erstellen und der Fortran-Code lässt sich nur extern einbinden, aber nicht inline. Ich finde das z.B. beim nvcc für CUDA gut gemacht, wo beim Compilieren C/C++-spezifischer Code vom CUDA-spezifischen Code getrennt und je vom CUDA-Compiler und vom GCC übersetzt und am Schluss die OBJ-Dateien vom GCC zusammengelinkt werden. Dies wäre natürlich ideal für mein Vorhaben. .NET und LLVM kommen für mich im Moment deshalb nicht infrage, weil da noch nicht die Plattformunterstützung soweit ist oder auch lizenzrechtlich noch nicht alles in trocknen Tüchern ist. Wäre ja super, wenn die GCC die .NET-Zwischensprache CIL und LLVM unterstützen würde, tun sie leider aber nicht. Da ich nun aber bei C++ primär bleiben möchte, suche ich nach Mittel und Wege, C/C++ irgendwie zu ergänzen. Ich danke vielmals im Voraus! MfG DITTY
  5. Hatte ich auch erst gedacht. Aber es würde mich wundern. Habs trotzdem getestet und nein, keine Verbesserung. Ja, da haste Recht. Ich wusste nicht so recht, wie ich das Phänomen bezeichnen sollte. Aber "Fehlverhalten" ist doch gar nicht mal so abwegig. Ich habe bewusst deshalb das Wort "Fehler" gemieden. Ein Fehlverhalten ist ja schließlich nicht das selbe wie ein Fehler. Aber dieses Verhalten kommt mir irgendwie als Folge eines Fehlers (z.B. Optimierungsfehler) vor. Oder habe ich irgendwas in meinem Code falsch gemacht / falsch angewendet (bezogen auf das Phänomen, nicht im Allgemeinen)? Schon klar. Doch in meinem Fall bzw. auf meinem System sollte man doch davon ausgehen können. Immerhin ändert sich ja im Augenblick nichts an meinem System, weder Software, noch Hardware. Also sollte doch der Opcode am Ende der selbe sein. Ja, so scheint die Vermutung. Wenn es so ist, wie kann ich es dann erkennen? Ich meine, ich hab mir schon den Assembler-Output angeschaut, aber so schlau werde ich nicht ganz drauß. Ich habs jetzt mal mit den zur Verfügung stehenden 128-Bit-Typen getestet. In meinem Beispiel statt uint64_t, also __uint128_t. Und siehe da. Es funktioniert und zwar mit allen Werten des Typs unsigned 64-Bit-INT (uint64_t). Aber so das Gelbe vom Ei ist die Lösung ja nicht. Das "Problem" mit uint64_t bleibt bestehen. Ich glaube, ich werde das Ganze mal als Bugreport einsenden. Außer jemand sieht das Problem schon an anderer Stelle bzw. weiß, wie man es richtig machen muss (insofern ich was falsch gemacht habe).
  6. Hab ich doch schon längst. Ebenso Frau Google und Herr Bing bemüht. Auch hab ich schon diverse Foren-SuFu´s bemüht. Mein Anliegen hier gibts schließlich nur, weil ich nicht mehr weiter weiß. Ja natürlich geht das. Produziert das dann nicht aber deutlich mehr Overhead und widerspricht dies dann nicht der 64-Bit-Programmierung? Ich meine: 64-Bit-Architektur vorhanden, ebenso: 64-Bit-System, 64-Bit-Compiler, 64-Libs und auch 64-Bit-INT-Typen. Warum sollte ich nicht davon Gebrauch machen dürfen??? Ich habe das Ganze jetzt noch um die INT-Literale ergänzt. Der Form halber, hier nochmal der aktuelle Code: #include <climits> #include <cstdint> #include <cinttypes> #include <cfloat> #include <cwchar> #include <string> //std::string #include <string.h> #include <cstring> #include <cstdlib> #include <cstdio> #include <iostream> #include <cmath> #ifdef _OPENMP #include <omp.h> #endif using namespace std; int main(int argc, char *argv[]) { uint64_t maxof = 0-1; const uint64_t NumValues = <Wert>ULL; uint64_t NumIterSingle = 0ULL; for(uint64_t i=0ULL;i<NumValues;i++) { NumIterSingle++; } printf("Benötigte Iterationen - SERIELL: %"PRIu64"\n",NumIterSingle); cout << "Referenz: " << NumValues << '\n'; cout << "MaxOf uint64_t: " << maxof << '\n'; getchar(); return 0; } Compile (Release): g++ -std=c++0x -m64 -fopenmp -Wall -Wextra -pedantic -pedantic-errors -O3 -s source -o dest Compile (Debug): g++ -std=c++0x -m64 -fopenmp -Wall -Wextra -pedantic -pedantic-errors -g -ggdb3 source.cpp -o dest g++-Version (gcc): gcc version 4.4.5 20110214 (Red Hat 4.4.5-6) (GCC) x86-64 Zur Erinnerung: setze man folgende Werte für "NumValues" ein: bis 9223372036854775807 // keine Probleme 9223372036854775808 // Problem ab 9223372036854775809 // keine ProblemeÜbersetzt wurde dabei mit Compile (Release). Wenn ich den Optimierungsschalter "-O3" weglasse, tritt das beschriebene Phänomen bei allen Zahlen auf. Lediglich bei Anwendung von "-O3", macht sich mir ein Fehlverhalten bemerkbar (siehe 9223372036854775808). Wie schon erwähnt, scheint der Compiler lediglich beim Wert 9223372036854775808 für NumValues, nicht richtig zu optimieren, da die Ausführungszeit Ewigkeiten dauert. Es verwirrt mich dahingehend, dass es nur bei dem Wert 9223372036854775808 auftritt (als wenn da nicht optimiert wurde). Alle anderen Werte, sprich bis 9223372036854775807 und ab 9223372036854775809 bis einschließlich dem Maximalwert von unsigned 64-Bit-INT: 18446744073709551615, funktionieren (das Programm wird also in kürzester Zeit in einem Rutsch abgearbeitet). Keine 128-Bit-Typen. Diesmal setze ich ausschließlich 64-Bit-Typen ein. Dabei ist es übrigens egal, ob ich die festen Typen a´la int64_t oder [unsigned] long long int verwende. Das Fehlverhalten bleibt das Gleiche. Das verwundert natürlich nicht, da die festen Typen auf 64-Bit-Systemen lediglich eine Typdefinition der normalen Typen sind (in meinem Fall also von unsigned long long int. Deshalb auch das Literal ULL). Ob mit oder ohne Literale, das Problem bleibt. Doch scheint mein Compiler diese Zahlen auch ohne Literale zu schlucken. Spuckt dann zwar Warnungen, aber es funktioniert. Wie Ihr oben seht, hab ich es dennoch der Richtigkeit halber mit Literale gemacht. Aber zum Vergleich: 9223372036854775809 und aufwärts funktionieren auch ohne Literale. Die Aktuelle Version von g++ ist eigentlich die 4.6.1 bzw. gar schon die Version 4.7. Wie oben erwähnt, ist die auf meinem System Aktuelle, noch die 4.4.5 (aktuellste aus den Paketquellen). Die Frage ist nun, ob das ein Eigenfehler von mir ist oder technisch bedingt bzgl. des Compilers, der Compiler-Option(en) und / oder der verwendeten Bilbiotheken? Kann jemand meinen Fall unter Verwendung obigen Codes und Compiler-Version+Schlatern überhaupt reproduzieren und ggfl. als Vergleich das Ganze mit einem anderen Compiler oder neuerer Compiler-Version ausprobieren, ob es das Fehlverhalten da immer noch gibt? THX! Und falls jemand das auf einen technischen Hintergrund beschränken kann, wo man selbst halt keine Handhabe mehr hat, was hättet Ihr dann noch für Tipps für mich, wie ich das Problem IRGENDWIE umschiffen kann? Ich muss nämlich definitiv mit solchen Größenordnungen hantieren. Besten THX und Grüße DITTY PS: Debugger hab ich auch schon verwendet, nur geht da alles reibungslos von statten. Ich kann auch mit dem Debugger nichts finden, was dieses Fehlverhalten -wenn es denn eins ist- mir erklären würde. Vlt. übersehe ich aber auch nur einfach was.
  7. @Leimy84: naja. Grundsätzlich haste Recht. Fakt ist aber, dass das Programm bei mir in kürzester Zeit abgearbeitet wird (vermutlich durch Compiler optimiert: Option -O3 ist nämlich an). Und dann erklärt das trotzdem nicht dieses Verhalten. Ich meine, mit: 9223372036854775807 funktionierts UND mit: 9223372036854775808 funktionierts nicht mehr. Bzw. was heißt "funktioniert nicht mehr"? Wie schon erwähnt, geht Ersteres in einem kurzen Rutsch durch. Letzteres benötigt Ewigkeiten (kA, wie lange, breche immer nach mehreren Minuten ab). Der Unterschied ist doch gerade mal eine einzige Iteration. Deshalb kann ich mir dieses Verhalten einfach nicht erklären. :confused: @flashpixx: Ja, na klar macht das Bsp.-Prog wenig Sinn. Die Grenzen auszulesen, ob per Lib-Variablen oder rechnerisch ist nicht das Problem. Das ist aber auch nicht das, was ich wissen möchte. Ich bin nur über die Verhaltensweisen unter entsprechenden Konstellationen verwundert und würde gerne die Gründe wissen bzw. wie man es besser / richtig machen müsste. Es müssen auf jeden Fall 64-Bit-Werte sein, da 32-Bit für meine späteren Anwendungszwecke (Physik, Astrophysik) einfach nicht mehr ausreichen. Selbst 64-Bit-Werte kommen da ab und zu an ihre Grenzen, weshalb ich später dann auch auf 128-Bit ausweichen muss. Bevor ich aber auf Drittlibs a´la GMP und Boost zurückgreife, wollte ich in erster Linie gerne erst einmal auf Möglichkeiten der Std-Libs und Compiler zurückgreifen. ---------------------------- So, nun zurück zum Thema. Jetzt bin ich ganz perplex. mit bzw. ab: 9223372036854775809 geht es wieder. Nochmals zum Vergleich: bis 9223372036854775807 // keine Probleme 9223372036854775808 // Problem ab 9223372036854775809 // keine Probleme Und jetzt erklärt mir das mal jemand??? Ich meine, ja gut, lasse ich eben den Wert weg, der Probleme bereitet. Aber das ist nicht gerade das Gelbe vom Ei. Woher soll man in Zukunft bei Berechnungen in diesen Größenordnungen denn wissen, welche Werte man meiden sollte und welche nicht?!? Grundsätzlich verstehe ich einfach nicht das Problem. Ist es Eigenverschulden, ne Macke des Compilers, der Compiler-Optionen, der verwendeten Libs, oder oder oder??? Ich würde gerne einfach mal mit meiner eigentlichen Programmierung anfangen wollen, nur dummerweise baut vieles auf den Umgang mit Datentypen auf. Selbst, wenn ich ne Drittlösung als Ausweg habe, etwa Drittlibs, würde ich gerne aus reiner Interesse dem nachgehen wollen. Die Frage hier ist ja schließlich nicht, eine Drittlösung zu finden, sondern mit den gegebenen Mitteln die Problemursachen ausfindig zu machen und ggfl. zu korrigieren bzw. richtig anzuwenden. Ich kanns mir nicht erklären. Vlt. ja einer von Euch. THX schon mal im Voraus! Grüße DITTY
  8. Hallo COM, zunächst einmal der Bsp.-Code: Test64_1.cpp #include <climits> #include <cstdint> #include <cinttypes> #include <cfloat> #include <cwchar> #include <string> //std:string #include <string.h> #include <cstring> #include <cstdlib> #include <cstdio> #include <stdio.h> #include <iostream> #include <cmath> #ifdef _OPENMP #include <omp.h> #endif using namespace std; int main(int argc, char *argv[]) { uint64_t maxof = 0-1; const uint64_t NumValues = 9223372036854775807; uint64_t NumIterSingle = 0; for(uint64_t i=0;i<NumValues;i++) { NumIterSingle++; } printf("Benötigte Iterationen - SERIELL: %"PRIu64"\n",NumIterSingle); cout << "Referenz: " << NumValues << '\n'; cout << "MaxOf uint64_t: " << maxof << '\n'; getchar(); return 0; } Compile mit: g++ -std=c++0x -m64 -fopenmp -Wall -Wextra -pedantic -pedantic-errors -O3 -s source -o dest Funktioniert. Zum Hintergrund: Ich möchte mit 64-Bit-Typen arbeiten. Ich bevorzuge die int64_t-Typen, weil ich fest definierte 64-Bit-Typen benötige und auf long bzw. long long, wollte ich nicht zurückgreifen, da systemabhängig. Ist ja auch egal, da die *_t-Typen lediglich typedef´s von bekannten Typen, wie long bzw. long long, sind. Im Gegensatz zu den eben genannten normalen Typen, welche je nach Compiler, Compiler-Option oder auch nach System unterschiedlich groß sein können, sind die *_t-Typen überall und unabhängig von Compiler, Compiler-Option und System, in ihre[r][n] Größe / Wertebereich fest definiert. Übersicht: signed 64-Bit: −9223372036854775808 bis 9223372036854775807 unsigned 64-Bit: 0 bis 18446744073709551615 Obiges Programm bestätigt dies für unsigned 64-Bit (uint64_t maxof = 0-1; ). Soweit alles richtig. Sobald ich aber für NumValues einen größeren Wert als 9223372036854775807 verwende, z.B. 9223372036854775808, wird zwar kompiliert und ein exec-File erzeugt, aber dieses bleibt dann quasi irgendwie hängen, wenn man es ausführt. Das Verhalten kann ich irgendwie nicht ganz nachvollziehen. Ebenso verändert sich der Compiler-Output bei einem Wert größer 9223372036854775807: Test64_1.cpp:28:30: warning: integer constant is so large that it is unsigned Test64_1.cpp:28: warning: this decimal constant is unsigned only in ISO C90 Mir ist schon bewusst, was diese Warnungen aussagen wollen, ich kann es nur nicht nachvollziehen. Bis zum Wert 9223372036854775807 scheints ja zu funktionieren. Ich versteh es dahingehend nicht, weil 9223372036854775807 lediglich das Maximum für signed 64-Bit (also int64_t) ist, ich aber unsigned 64-Bit (uint64_t) verwende, wo z.B. auch 9223372036854775808 locker hineinpassen sollte. Der erste Test funktioniert ja und ein: uint64_t maxof = 0-1;offenbart, dass Werte größer 9223372036854775807 (max. bis 18446744073709551615), angenommen werden und funktionieren. Warum bleibt das Programm förmlich stehen? Ich meine, es tut sich minutenlang nichts, sodass ich mit STRG+C beenden muss. Hat jemand Vorschläge, Lösungen, etc.? EDIT: Es muss etwas mit der for()-Schleife zu tun haben. Wenn ich diese auskommentiere, funktioniert nämlich alles, sprich, z.B. wird NumValues = 9223372036854775808, am Ende auch korrekt ausgegeben. Nur weshalb das mit ner for()-Schleife nicht funktionieren sollte, bleibt mir ein Rätsel!???! Ich meine 9223372036854775807 funktioniert, auch mit der for()-Schleife. Besten Dank im Voraus! Grüße DITTY :):)
  9. Also seht Ihr keinerlei Chance, dass printf(,) in der jetzigen Form, nicht mit den beiden Datentypen __int128_t und __uint128_t umgehen kann? Also was Ausgabe betrifft.
  10. Also ich habe zwei Schleifen. Einmal (äußere Schleife) die der Tastaturabfrage mit [my_]kbhit() und [my_]getch() und dann noch die Iterationschleife für die Variableniteration (innere Schleife)? Wie genau meinst Du das? Wenn die äußere Schleife den Status der Tastatur erfragt, aber nichts gedrückt wurde, würde doch false herauskommen und die gesamte Schleife übersprungen werden. Und wie soll auf beiden Schleifen jeweils die Hälfte (Bsp. 1000 und 1000 = 1 Mio) verteilt werden, wenn es doch bei 0 anfängt? Es soll ja hochgezählt werden. Natürlich könnte ich die Grenze festlegen und dann der äußeren, wie der inneren Schleife jeweils entsprechend iterieren lassen, woraus sich letztendlich dann wieder die Grenze als Ergebnis ergeben würde, da Anzahl Iterationen äußerer Schleife mal Anzahl Iterationen innere Schleife. Aber eine Grenze möchte ich ja nicht festlegen. Im Gegenteil. Bei dem Bsp.-Prog. versuche ich ja die Grenze eines Datentyps via Schleife zu ermitteln, die Grenze ist also Anfangs unbekannt und kann daher nicht auf beide Schleifen verteilt werden. Grüße DITTY
  11. Habt großen Dank. Habs soweit jetzt hinbekommen. Hier ein Bsp.-Prog. für std::cout: INTS128.cpp: #include <climits> #include <cstdint> #include <cinttypes> #include <cfloat> #include <cmath> #include <cstdlib> #include <cstdio> #include <stdio.h> #include <iostream> using namespace std; std::ostream &operator<<(std::ostream &out, __uint128_t x) { if(x >= 10) { out << x / 10; } return out << static_cast<unsigned>(x % 10); } std::ostream &operator<<(std::ostream &out, __int128_t x) { if(x < 0) { out << '-'; x = -x; } return out << static_cast<__uint128_t>( x); } int main(int argc, char *argv[]) { __int128_t Var31 = 0, tmp31 = 0; __uint128_t Var32 = 0, tmp32 = 1; cout << "128-Bit Integer\n-----------------\n"; __int128_t INT128_MIN = (-170141183460469231731.687303715884105728) * pow(10,18); __int128_t INT128_MAX = ( 170141183460469231731.687303715884105727) * pow(10,18); //cout << "Vermutet:\nINT128-MIN:" << INT128_MIN << "\nINT128-MAX: " << INT128_MAX << "\n\nBerechnet:\n"; __int128_t TMP128 = 0; TMP128 = INT128_MAX + 1; // ergibt INT128-MIN cout << "INT128-MIN: " << TMP128 << "\n"; // Ausgabe von INT128-MIN TMP128 = INT128_MIN - 1; // ergibt INT128-MAX cout << "INT128-MAX: " << TMP128 << "\n"; // Ausgabe von INT128-MAX __uint128_t UINT128_MAX = (340282366920938463463.374607431768211455) * pow(10,18); __uint128_t UINT128_MIN = 0/* * pow(10,18)*/; __uint128_t TMPu128 = 0; TMPu128 = UINT128_MAX + 1; // ergibt UINT128-MIN cout << "UINT128-MIN: " << TMPu128 << "\n"; // Ausgabe von UINT128-MIN TMPu128 = UINT128_MIN - 1; // ergibt UINT128-MAX cout << "UINT128-MAX: " << TMPu128 << "\n"; // Ausgabe von UINT128-MAX getchar(); return 0; } OS: Linux x64-86 (bei mir Scientific Linux 6.1 x64 (up2date)) g++(GCC)-Version: g++ (GCC) 4.4.5 20110214 (Red Hat 4.4.5-6) Glibc: x86_x64 - v2.12-1.25.el6_1.3 Compile (release): g++ -std=c++0x -m64 -fopenmp -Wall -Wextra -pedantic -pedantic-errors -O3 -s source.cpp -o dest Output (exec): 128-Bit Integer ----------------- INT128-MIN: -170141183460469231731687303715884105728 INT128-MAX: 170141183460469231731687303715884105727 UINT128-MIN: 0 UINT128-MAX: 340282366920938463463374607431768211455 ----------------------- Wüsste noch jemand, wie man auch printf(,) dies beibringen kann? Und kann man und wenn ja wie, printf(,) weitere Makros beibringen? Ich wüsste da zwar jetzt ne Möglichkeit einfach einen Output mittels std:cout in eine String- bzw. char[]-Variable zu stecken und diese fprint(,) zu übergeben, allerdings würde ich nur ungern printf(,) mit std::cout kreuzen wollen. Lieber wäre mir, wenn ich wahlweise mein überladenes std::cout oder printf(,) verwenden könnte, ohne dass das eine vom anderen abhängig ist. THX im Voraus, Grüße DITTY
  12. Ich weiß, ischweiß Da das aber nicht der Fall war, hab ichs sein gelassen. Insb. bei Vererbung machts Sinn, da Konstruktorinitialisierung. Dennoch, wenn nicht CONST- oder Referenzmember, bevorzuge ich den Weg über Konstruktor-Körper. Outline oder Inline, je nach Codeumfang für den/die Konstruktor(en). Scheint aber ne Frage des Geschmacks sein. Technisch sehe ich da keinen Unterschied (korrigiert mich, wenn ich falsch liege). Gut, dachte ich mir schon. Aber das setzt wieder eine Compilerabhängigkeit voraus. Sicher, jeder gute Compiler unterstützt dies. Ich finde trotzdem, dass die eine kleine Zeile am Ende einer Funktion / der main()-Funktion nicht schaden kann. Findet ja nicht nur bei main() Anwendung, sondern auch bei anderen Funktionen. Hässlicher finde ich es, wenn jemand Funktionen mit Rückgabetyp, aber fehlender return-Anweisung schreibt. Deshalb wende ich das grundsätzlich bei allen Funktionen mit Datentyp !(void) an, die main()-Funktion eingeschlossen. Hm, finde ich nicht. Denn a.) ist es nur eine Warnung, keine Fehlermeldung und b.) erinnert es einem Programmierer immer wieder daran, dass es sich gehört ein RETURN zu werfen, wenn Rückgabedatentyp angegeben ist. Und nein, natürlich hab ich es nicht als Fehler verstanden und auch nicht angemerkt. Es wiedersprach einfach meinen Designprinzipien und sollte vielmehr ein gut gemeinter Tipp sein, kein MustHave. -------------------- Zu den Standard-Auszügen. Hab großen Dank. Ich hab mir jetzt aber angewöhnt, gleich im neuen 10-/11er-Standard zu proggen. Wird aber gewiss ähnlich oder gleich sein. Angesichts vieler gerade laufender Projekte komme ich leider nicht dazu, das nachzuschlagen, zumal es ja nicht falsch oder fehlerhaft ist, wenn man Konstruktoren, Destruktoren und return-Anweisungen grundsätzlich angibt. Grüße DITTY
  13. Hi, Wusste ich noch gar nicht. Wieder was gelernt. Kann man das denn irgendwo nachlesen (Quellen bitte)? Wie schauts mit dem Destruktor aus? Ja, meinte beim ersten eigentlich, das Mitgeben von Parametern. Inline bringt selbstverständlich nicht wirklich einen Vorteil, technisch zumindest nicht. Übertreiben müssen wirs bei so einem einfachen KLEINEN Beispiel aber nicht. Gerade bei diesem Konstruktor bietet sich Inline Zwecks Lesbarkeit aber an. Wegen Initialisierungsliste: ich wollte ihn nicht überfordern. Natürlich bietet sich auch eine Initialisierungsliste an, finde ich aber ehrlich gesagt manchmal auch unübersichtlich, je nach Anzahl zu initialisierender Variablen. Ach, man liest hier und da immer wieder Verschiedenes. Was hätte es denn technisch für eine Auswirkung, wenn man trotzdem "return 0" bei "int main(){}" mitführt? Ich machs halt immer mit. 2 Sekunden Tipparbeit hat noch keinen geschadet. Ebenso verschwinden so auch lästige Compiler-Warnungen. Grüße DITTY :D:D:D
  14. Hmmmm (überleg). Wär auch ne Möglichkeit. Würde der Overhead dabei aber nicht der Gleiche bleiben? Schließlich würden dann trotzdem die Funktionen my_getch() und my_kbhit() bei jeder Iteration ausgeführt werden. Oder hab ich dich missverstanden? Und gibts auch andere Möglichkeiten einer Tasteneingabeauswertung ohne ENTER? Keine selbstgeschriebenen Funktionen, sondern Std-Funktionen, Libs, System, etc.? Grüße DITTY
  15. Irgendwie reden Wir Heute aneinander vorbei . Bin dennoch sehr dankbar für Eure Hilfen!!! (DAUMEN HOCH, gibts leider nicht als Smile => Anregung) Stimmt. Na gut, klärt das Eine. Ich würde gerne aber lieber mit printf(,) oder std:cout arbeiten wollen. Ich kann mir beim besten Willen nicht vorstellen, dass die die Ausgabemöglichkeit vergessen haben, als se die 128-Bit-Integer implementiert haben. Mit __int64_t funktionierts doch auch, dank Makro und std:cout unterstützt´s direkt. Gibt es für printf() vlt. ein Makro für die genannten 128-Bit-Integer? Wie gesagt, "long double" selbst mit 2^512 unterstützt´s ja auch. Ja gut, Standard. Aber wenn jemand so einen Datentyp wie __int128_t implementiert, muss er es doch auch mal ausgegeben haben. Ich sehe in den Dokus nüscht. Kann da vlt. jemand mal schauen? Vlt. übersehe ich ja was Essentielles. Ja, schon klar. Mir gehts rein vom Interesse aus. Wie ich das mit 64-Bit-Integer handhabe, weiß ich ja, wie ich bereits geschrieben habe. Mir gehts aber EXPLIZIT um diese beiden implementierten 128-Bit-Integer. THX und Grüße DITTY

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...