WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Matrix als formatierte Stringausgabe

 

Xirpy
Forum-Newbie

Forum-Newbie


Beiträge: 6
Anmeldedatum: 16.09.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 27.09.2013, 14:24     Titel: Matrix als formatierte Stringausgabe
  Antworten mit Zitat      
Hallo goMatlab-Forum-Gemeinde,
ich bin noch nicht richtig fit in Matlab und hoffe ihr könnt mir behilflich sein.

Wenn ich eine Matrix mit Elementen unterschiedlicher Wertigkeit habe...
Code:
M = [3.124578 5.47e+5 1.25e-3; 55 32.15421478569854 2.5e-6];
 

...wie kann ich es erreichen, dass mit sprintf folgende Ausgabe erscheint:
Code:
[[3.124578, 547000, 0.00125],[55, 32.15421478569854, 0.0000025]]

Soll heißen - ich möchte weder ein Genauigkeitsverlust noch eine Exponentialschreibweise. Auch die eigenwillige Formatierung soll beibehalten werden.
Ich habe mich bis jetzt wie folgt dem Problem gewidmet:
Code:
M = [3.124578 5.47e+5 1.25e-3; 55 32.15421478569854 2.5e-6];
dim = size(M);
string = repmat('%f, ',1,dim(2));
string = string(1:end-2);
string = ['[',string,'],'];
string = repmat(string,1,dim(1));
string = string(1:end-1);
spring = ['[',string,']'];
sprintf(string,M);
 

Ist aber bis jetzt nicht zielführend.
Danke im vorraus.
Private Nachricht senden Benutzer-Profile anzeigen


Winkow
Moderator

Moderator



Beiträge: 3.842
Anmeldedatum: 04.11.11
Wohnort: Dresden
Version: R2014a 2015a
     Beitrag Verfasst am: 27.09.2013, 14:33     Titel:
  Antworten mit Zitat      
Code:
M = [3.124578 5.47e+5 1.25e-3; 55 32.15421478569854 2.5e-6];
sprintf('[[%.6f, %6.0f, %.5f],[%.0f, %.14f, %.7f]]',M')

wie man den format spec macht steht in der doc zu sprintf unter formatSpec oder Formatting Strings
_________________

richtig Fragen
Private Nachricht senden Benutzer-Profile anzeigen
 
Xirpy
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 6
Anmeldedatum: 16.09.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 27.09.2013, 15:01     Titel:
  Antworten mit Zitat      
Vielen Dank für deine schnelle Antwort.
Sie löst aber leider noch nicht mein Problem, da ich mich nicht richtig ausgedrückt habe.
Du hast jetzt ja die Formatierungen hart ins sprintf reingeschrieben. Ich möchte aber später unterschiedliche Matrizen aus unterschiedlichen Files laden von den ich die Länge und Wertigkeit der einzelnen Elemente nicht kenne. Somit muss sich die Formatierung immer wieder auf die eingelesen Matrix adaptieren können.
Private Nachricht senden Benutzer-Profile anzeigen
 
Winkow
Moderator

Moderator



Beiträge: 3.842
Anmeldedatum: 04.11.11
Wohnort: Dresden
Version: R2014a 2015a
     Beitrag Verfasst am: 27.09.2013, 15:03     Titel:
  Antworten mit Zitat      
das problem ist das ich keinen hintergrund in deinem formatierungsbeispiel sehe ^^. keine regel. darum kann ich das auch nicht automatisieren ^^ jeden string gleich zu formatieren oder die ersten 6 einträge oder was auch immer ist leicht. aber eine vorschrift für eine willkürliche formatierung ist hart ^^.
erkläre doch nochmal genau wie die einträge formatiert werden sollen. wie die werte vorliegen etz. was dir das command window anzeigt und was in der matrix gespeichert ist sind 2 paar schuhe ^^
_________________

richtig Fragen
Private Nachricht senden Benutzer-Profile anzeigen
 
Xirpy
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 6
Anmeldedatum: 16.09.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.09.2013, 16:26     Titel:
  Antworten mit Zitat      
Ich versuche es aufs Wesentlich zu reduzieren.
Mir geht es prinzipiell darum, einen ganzen Satz von verschiede Variablen (Skalar, Vektor, Matrix) einzulesen z.B. durch den Aufruf eines m-Skripts oder einer *.mat. Diese sich im Workspace befindlichen Variablen möchte ich gerne als String formatiert ausgeben, sei es in einer *.txt oder *.xml zur Weiterverarbeitung in anderen Programmen oder einfach über das Prompt. Hierbei sollte sich der Inhalt der Variable nicht verändern durch z.B. das Abschneiden von Zahlen oder Rundungen. Außerdem sollte die Zahl später nicht in Exponentialdarstellung vorliegen und keine nachfolgenden Nullen führen.

Ein Lösungsansatz habe ich mittlerweile finden können. Hier mal ein kleines Beispiel für zwei skalare Variablen, wobei ich hier die Kommastellen ermittle und dann mit .* die Auflösung festlege:
Code:
clear all, clc

% erste Variable
variable1   = 1.123456789;
string1       = num2str(variable1, '%32.16g');
resoultion2 = length(string1) - find(string1 == '.');
fprintf('%.*f\n',resoultion2,variable1);

% zweite Variable
variable2   = 1.123456789e-5;
string2       = num2str(variable2, '%32.16g');
resoultion2 = length(string2) - find(string2 == '.');
fprintf('%.*f\n',resoultion2,variable2);


Gibt es noch eine andere Möglichkeit die Auflösung zu ermitteln und wie mache ich das Ganz jetzt bei Matrizen und Vektoren mit ganz unterschiedlichen Wertigkeiten der einzelnen Elemente?
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 30.09.2013, 17:34     Titel:
  Antworten mit Zitat      
Hallo Xirpy,

Wie schon mal an anderer Stelle erwähnt, würde ich unbedingt das "clear all" weglassen. Wozu soll das nützlich sein? Da es auch alle Breakpoints löscht, behindert die das Debuggen.

Ich verstehe noch nicht den Zweck der von Dir gesuchten Funktion. Wenn Deine Lösung für einen Skalar funktioniert, kannst Du sie doch einfach in einer Schleife aufrufen, um eine Matrix zu bearbeiten, oder?

Zitat:
Hierbei sollte sich der Inhalt der Variable nicht verändern durch z.B. das Abschneiden von Zahlen oder Rundungen.

Dies ist eine unlösbare Aufgabe. Zahlen werden intern ja im Binär-Format gespeichert. Nun haben die meisten Dezimalzahlen keine exakte Darstellung im Binär-Format, wenn beide nur mit begrenzter Genauigkeit gespeichert werden. Umgekehrt gilt dies auch, also sind Fließkommazahlen im Binär-Format nicht generell exakt im Dezimal-Format darstellbar. Ein immer wieder auftauchendes Beispiel ist:
Code:
0.3 - 0.2 - 0.1

Das sieht so sehr nach 0 aus, dass Matlab-Nutzer (betrifft aber jede andere Programmiersprache, die den IEEE754-Standard benutzt) immer wieder verwundert sind, dass dies -2.775e-017 ergibt.
Die Konvertierung zwischen Binär- und Dezimal-Format lässt sich also nicht ohne rundung oder Abschneiden von Ziffern bewältigen. Du kannst zwar eine Menge Tricks versuchen, um den Einfluss zu verkleinern. Die V8-Bibliothek von Google benötigt für ein möglichst gutes FSCANF/FPRINTF auch mal eben 8 MB Source-Code. Aber auch damit lässt sch nicht verhindern, dass 0.3 intern eben 0.299999999999999 ist. Die Darstellung als 0.3 im Command-Window ist also bereits eine mehr oder weniger willkürliche Rundung.

Wenn Du wirklich Dezimal-Zahlen exakt in ein XML-File schreiben möchtest, musst Du die Binär-Zahlen zunächst in UINT8 aufteilen und dann als HEX- oder Base64 kodieren.
Code:
x = pi;
data = typecast(x, 'uint8');
string = sprintf('%.2x', data);

Als Base64 wäre dies 'GC1EVPshCUA', also etwas kompakter.

Gruß, Jan



Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Xirpy
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 6
Anmeldedatum: 16.09.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 10.10.2013, 13:06     Titel:
  Antworten mit Zitat      
Besten Dank für eure Antworten und entschuldigt das ich mich jetzt erst melde.

Mittlerweile habe ich eine Funktion geschrieben die mir einen formatierten String für ein Skalar, ein Vektor oder einer Matrix ausgibt. Leider sind die numerischen Fehler, wie Jan sie beschrieben hat, weiterhin nicht wegzubekommen.

Code:
function [FinalString] = getResolution(Value)
Dimensions = size(Value);
    if isequal(Dimensions(1),1) && isequal(Dimensions(2),1) % Skalar
        InString    = num2str(Value,'%32.16g');
        Resolution  = length(InString) - find(InString == '.');
        FinalString = ['%.',num2str(Resolution),'f'];
    elseif ((isequal(Dimensions(1),1) && ~isequal(Dimensions(2),1))||(~isequal(Dimensions(1),1) && isequal(Dimensions(2),1))) % Vektor
        FinalString = '';
        BufferString = '';
        for i = 1:length(Value)
            InString = num2str(Value(i),'%32.16g');
            if strfind(InString,'e') >= 0
                pos = strfind(InString,'e');
                ePos = InString(pos+1:end);
                xnum = str2num(ePos);
                Resolution{i} = (pos - 1) - find(InString == '.') + abs(xnum);
            else
                Resolution{i} = length(InString) - find(InString == '.');
                EmptyCells = cellfun(@isempty,Resolution);
                if EmptyCells(i)
                    Resolution{i} = 0;
                end
            end
            CurrentString   = ['%.',num2str(Resolution{i}),'f, '];
            BufferString    = [BufferString,CurrentString];
        end
        FinalString = BufferString(1:end-2);
        FinalString = ['[',FinalString,']'];
    else % Matrix
        Value = Value';
        idx = 0;
        FinalString = '';
        for i = 1:Dimensions(1)
            BufferString = '';
            for k = 1:Dimensions(2)
                idx = idx + 1;
                InString = num2str(Value(k),'%32.16g');
                if strfind(InString,'e') >= 0
                    pos = strfind(InString,'e');
                    ePos = InString(pos+1:end);
                    xnum = str2num(ePos);
                    Resolution{idx} = (pos - 1) - find(InString == '.') + abs(xnum);
                else
                    Resolution{idx} = length(InString) - find(InString == '.');
                    EmptyCells = cellfun(@isempty,Resolution);
                    if EmptyCells(idx)
                        Resolution{idx} = 0;
                    end
                end
                CurrentString   = ['%.',num2str(Resolution{idx}),'f, '];
                BufferString    = [BufferString,CurrentString];
            end
            BufferString = BufferString(1:end-2);
            BufferString = ['[',BufferString,'],'];
            FinalString = [FinalString,BufferString];
        end
        FinalString = FinalString(1:end-1);
        FinalString = ['[',FinalString,']'];
    end
end


Evtl. hat jemand ja noch eine Verbesserungsidee... Rolling Eyes
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 10.10.2013, 15:12     Titel:
  Antworten mit Zitat      
Hallo Xirpy,

Diese numerischen Effekte kann man gar nicht "wegbekommen", denn sie sind Bestandteil der Methode Zahlen intern im Binärformat zu speichern und das Dezimal-Format für die Darstellung zu verwenden.
Das Problem löst sich sofort und ohne jegliche Tricks, wenn man entweder nur das Dezimal- oder nur das Binär-Format verwendet. Letzteres geschieht z.B. wenn man Zahlen per FWRITE im Biär-Format schreibt: Das ist schneller und vermeidet die zwei(!) Konvertierungen, die definitionsgemäß mit Rundungsfehlern behaftet sein müssen.

Statt "if isequal(Dimensions(1),1) && isequal(Dimensions(2),1)" ist dies viel sicherer: "if numel(Value) == 1".
Eine zuverlässige Methode müsste noch 3 und mehr Dimensionen abfangen.

Ich habe zu viele Versuche gesehen die Ausgabe der jahrelang massiv getesteten SPRINTF/SSCANF-Bibliotheken zu verbessern, die dabei als Bugs oder aus Unkenntnis der Details Fehler enthielten. Nichmal MathWorks hat diese Befehle selbst geschrieben, sondern dazu bestehende C-Routinen verwendet, weil sie einfach viele millionen Male getestet und über Jahrzehnte verbessert wurden. Deshalb rate ich von händischen "Verbesserungen" dringend ab und würde sie unter keinen Umständen für produktive Arbeit verwenden. Wenn man mal ein paar Milliarden Zahlen in Files geschrieben hat um sie für eine Wissenschaftliche Studie auszuwerten, wäre ein noch so kleiner Bug ein Desaster.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.