|
|
1.1 root 1: /*
2: * Factor prints out the prime factorization of numbers. If there are
3: * any arguments, then it factors these. If there are no arguments,
4: * then it reads stdin until either EOF or the number zero or a non-numeric
5: * non-white-space character. Since factor does all of its calculations
6: * in double format, the largest number which can be handled is quite
7: * large.
8: */
9: #include <stdio.h>
10: #include <math.h>
11: #include <ctype.h>
12:
13:
14: #define NUL '\0'
15: #define ERROR 0x10 /* largest input base */
16: #define MAXNUM 200 /* max number of chars in number */
17:
18:
19: main(argc, argv)
20: int argc;
21: register char *argv[];
22: {
23: register char *chp;
24: double n;
25: double atod();
26: char *getnum();
27:
28: if (argc != 1)
29: while ((chp=*++argv) != NULL && (n=atod(chp)) != 0)
30: factor(n);
31: else
32: while ((chp=getnum()) != NULL && (n=atod(chp)) != 0)
33: factor(n);
34: return (0);
35: }
36:
37:
38: die(str)
39: char *str;
40: {
41: fprintf(stderr, "%r\n", &str);
42: exit(1);
43: }
44:
45: usage()
46: {
47: die("usage: factor [number number ...]");
48: }
49:
50:
51: char *
52: getnum()
53: {
54: register char *chp,
55: ch;
56: static char res[MAXNUM+1];
57:
58: do {
59: ch = getchar();
60: } while (isascii(ch) && isspace(ch));
61: if (!isascii(ch) || todigit(ch) == ERROR)
62: return (NULL);
63: for (chp=res; isascii(ch) && !isspace(ch); ch=getchar())
64: if (chp < &res[MAXNUM])
65: *chp++ = ch;
66: if (chp >= &res[MAXNUM])
67: die("Number too big");
68: *chp++ = NUL;
69: return (res);
70: }
71:
72:
73: /*
74: * Atod converts the string `num' to a double and returns the value.
75: * Note, that if there is a non-digit in the string, or if there is
76: * an overflow, then it exits with an appropriate error message.
77: * Also note that atod accepts leading zero for octal and leading
78: * 0x for hexidecimal, and that in the latter case, a-f and A-F are
79: * both accepted as digits.
80: */
81: double
82: atod(num)
83: char *num;
84: {
85: register char *str;
86: register int i;
87: double res = 0,
88: base = 10;
89:
90: str = num;
91: i = *str++;
92: if (i == '0')
93: if ((i=*str++) == 'x') {
94: i = *str++;
95: base = 0x10;
96: } else
97: base = 010;
98: for (; i != '\0'; i=*str++) {
99: i = todigit(i);
100: if (i >= base)
101: die("bad number `%s'", num);
102: res = res * base + i;
103: if (res+1 == res)
104: die("Number too big `%s'", num);
105: }
106: return (res);
107: }
108:
109:
110: /*
111: * Todigit converts the char `ch' to an integer equivalent, assuming
112: * that `ch' is a digit or `a'-`f' or `A'-`F'. If this is not true,
113: * then it returns ERROR.
114: */
115: todigit(ch)
116: register int ch;
117: {
118: if (!isascii(ch))
119: return (ERROR);
120: if (isdigit(ch))
121: return (ch - '0' + 0);
122: if (isupper(ch))
123: ch = tolower(ch);
124: if ('a' <= ch && ch <= 'f')
125: return (ch - 'a' + 0xa);
126: return (ERROR);
127: }
128:
129:
130: /*
131: * Factor is the routine that actually factors the double `n'.
132: * It writes the prime factors to standard output.
133: */
134: factor(n)
135: double n;
136: {
137: double temp,
138: limit,
139: try;
140:
141: while (n > 1 && modf(n/2, &temp) == 0) {
142: printf("2 ");
143: n = temp;
144: }
145: limit = sqrt(n);
146: for (try=3; try <= limit; try += 2) {
147: if (modf(n/try, &temp) != 0)
148: continue;
149: do {
150: printf("%.0f ", try);
151: n = temp;
152: } while (modf(n/try, &temp) == 0);
153: limit = sqrt(n);
154: }
155: if (n > 1)
156: printf("%.0f", n);
157: putchar('\n');
158: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.