2017-05-07 7 views
0

Ich habe ein Problem mit einigen integrierten Funktionen für C. Grundsätzlich, was ich versuche zu erstellen, ist meine eigene colpitts Oszillator Rechner, der die folgenden Eingaben in der Reihenfolge als Argumente nimmt: Induktor Wert, Kondensatorwert, zweiter Kondensatorwert.strtoll und division nicht korrekte Zahlen zurück

Eingänge können in F oder H enden und können auch ein Präfix p, m, n und u haben, um pico, milli, nano und micro darzustellen. Die Ausgabe wird auch formatiert, wenn die Zahl zu groß ist und ein Suffix angehängt wird.

Das Problem, das ich nach dem Einfügen der Debug printf-Anweisungen mit meinem Programm habe, ist, dass die Zahlenumwandlung nicht korrekt ist.

Ich habe die Test Argumente wie die folgende in dieser Reihenfolge verwendet:

1p 2pF 3F 

Dies ist meine erste Ausgabe:

DEBUG Init proc: 1p      
DEBUG post proc: 0.000000    
DEBUG Init proc: 2p      
DEBUG post proc: 0.000000    
DEBUG Init proc: 3      
DEBUG post proc: 3.000000 

Aber die DEBUG Post proc Linien sind falsch mit Ausnahme des letzten.

wollte ich sehen:

DEBUG Init proc: 1p      
DEBUG post proc: 0.000000000001    
DEBUG Init proc: 2p      
DEBUG post proc: 0.000000000002    
DEBUG Init proc: 3      
DEBUG post proc: 3.000000 

Dies ist mein Code:

#include <stdio.h> 
#include <math.h> 
#include <stdlib.h> 
int main(int argc,char* argv[]){ 
    if (argc < 4){ 
printf("Need 3 args: L, C1, C2. %d supplied\n",argc-1);return -1; 
    } 
    long double nums[4],f;long isnum; 
    int n=0; 
    for (n=1;n<4;n++){ 
//process each arg 
char *p=argv[n];while(*p != '\0'){p++;};p--; 
//strip last character if it's F, f, H, or h 
if (*p=='F' || *p=='f' || *p=='H' || *p=='h'){*p='\0';p--;} 
printf("DEBUG Init proc: %s\n",argv[n]); 
switch (*p){ 
    case '0': //do nothing if new last character is a number 
    break; 
    case 'p': //convert picounit to unit 
    *p='\0'; 
    nums[n]=strtoll(argv[n],NULL,10)/1000000000000ULL; 
    break; 
    case 'n': //convert nanounit to unit 
    *p='\0'; 
    nums[n]=strtoll(argv[n],NULL,10)/1000000000ULL; 
    break; 
    case 'u'://convert microunit to unit 
    *p='\0'; 
    nums[n]=strtoll(argv[n],NULL,10)/1000000ULL; 
    break; 
    case 'm'://convert milliunit to unit 
    *p='\0'; 
    nums[n]=strtoll(argv[n],NULL,10)/1000ULL; 
    break; 
    default: //do nothing if new last character is a number from 1 to 9 or print error if it isn't u,m,n or p. 
    isnum=strtol(p,NULL,10); 
    if (isnum < 1 || isnum > 9 || isnum=='\0'){ 
    printf("Number %d is in bad format. Use suffix of either: uH mH nH pH uF mF nF pF\n",n); 
    return -1; 
    } 
    nums[n]=strtoll(argv[n],NULL,10); 
} 
printf("DEBUG post proc: %Lf\n",nums[n]); 
    } 
    printf("Input values: %Lf,%Lf,%Lf\n",nums[1],nums[2],nums[3]); 
    //calculate frequency 
    f=1/(2*3.14159)*sqrt(nums[1]*((nums[2]*nums[3])/(nums[2]+nums[3]))); 
    char suf=' '; //prepare suffix to display frequency in user friendly format 
    if (f > 1000000){f=f/1000000;suf='M';} //convert to Mhz if f > 1000000 
    if (suf=='\0' && f > 1000){f=f/1000;suf='K';} 
    printf("Frequency = %Lf %c hz\n",f,suf); 
    return 0; 
} 

Wie ich einen Prozessor 32-Bit nur für die Arbeit mit, ich fühle mich dazu, meine Antworten sind begrenzt. Was kann ich tun, um dieses Problem zu beheben?

+1

Sie tun Ganzzahl Division, daher das Ergebnis von z. 'strtoll (argv [n], NULL, 10)/1000000000000ULL' ist (wahrscheinlich) 0 (ein int); Wenn Sie das in double umwandeln, bleibt es 0. Teilen Sie es stattdessen durch 1000000000000,0, um die Gleitkommadivision zu erzwingen. – Evert

+0

Ok, ich habe .0 zu allen großen Zahlen hinzugefügt und es hilft nicht. – Mike

+0

Ihr Code wird außerhalb der Grenzen zugreifen, wenn ein Argument von nur "F" gegeben wird –

Antwort

2

Zuerst - wie von Evert erwähnt - machen Sie Integer-Divisionen. Schreiben nums[n]=strtoll(argv[n],NULL,10)/(1000000000000.0); oder nums[n]=((double)strtoll(argv[n],NULL,10))/1000000000000ULL sollte dieses Thema lösen.

Sobald Ihre Zahlen korrekt sind, wird der Ausgang wohl zum 6. Dezimalstelle gerundet:

C99 §7.19.6.1 Die fprintf Funktion, f, F

Ein double Argument a darstellt Die Fließkommazahl wird im Stil [−]ddd.ddd in Dezimalschreibweise konvertiert, wobei die Anzahl der Stellen nach dem Dezimalzeichen gleich der Genauigkeitsangabe ist. Wenn die Genauigkeit fehlt, wird es als 6 genommen; ...

Schreiben Sie printf("DEBUG post proc: %1.15Lf\n",nums[n]) und Sie sollten die Reste sehen.

+0

Das 1.15 Teil funktioniert gut für mich. – Mike

+1

Bei solch kleinen Zahlen ist die Verwendung des 'e' Formatiers wahrscheinlich geeigneter. – Evert

+0

Beide 'nums [n] = strtoll (argv [n], NULL, 10)/(1000000000000.0); noch nums [n] = ((doppelter) strtoll (argv [n], NULL, 10))/1000000000000ULL' steht kurz bevor. Der Quotient kann mit "double" math berechnet werden, das Ergebnis wird jedoch in einem 'long double' gespeichert. Schlagen Sie Folgendes vor: nums [n] = strtoll (argv [n], NULL, 10)/1.0e12L'; – chux

Verwandte Themen