(%i1) e : a^2 + b^2 + c^2;
2 2 2
(%o1) c + b + a
(%i2) ratsubst(r^2, a^2 + b^2 + c^2, e);
2
(%o2) r
(%i3) e : - 3 * a^2 - 3 * b^2 - 3 * c^2;
2 2 2
(%o3) - 3 c - 3 b - 3 a
(%i4) ratsubst(r^2, a^2 + b^2 + c^2, e);
2
(%o4) - 3 r
An occasionally updated blog, mostly related to programming. (Views are my own, not my employer's.)
Monday, June 9, 2008
substitute expressions in Maxima
From the Maxima mailing list: Say you want to substitute one expression for another, also dealing with the case in which the expression to be replaced is multiplied by some constant.
if every vector in a list has the same length, create a matrix
matrixIfAllSameLen <- function(a.list) {
if (length(unique(unlist(lapply(a.list, length)))) == 1) {
n <- length(a.list[[1]])
return(matrix(unlist(a.list), ncol=n, byrow=TRUE))
}
else {
return(a.list)
}
}
if (length(unique(unlist(lapply(a.list, length)))) == 1) {
n <- length(a.list[[1]])
return(matrix(unlist(a.list), ncol=n, byrow=TRUE))
}
else {
return(a.list)
}
}
Saturday, June 7, 2008
Getting a quiet NaN in C
nan.c:$ gcc nan.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
double x = strtod("NAN", 0);
printf("%f\n", x);
printf("%d\n", (int)(x == x));
return 0;
}
$ ./a.out
nan
0
This is portable, right?
nan1.c:$ gcc nan1.c
#include <math.h>
#include <stdio.h>
int main()
{
printf("%f\n", NAN);
return 0;
}
$ ./a.out
nan
Is this portable??
I'm working under Mac OS X 10.4 here. Let's see if these programs work under Red Hat Linux. Yes and no:
vincent% gcc nan1.c
nan1.c: In function ‘main’:
nan1.c:6: error: ‘NAN’ undeclared (first use in this function)
nan1.c:6: error: (Each undeclared identifier is reported only once
nan1.c:6: error: for each function it appears in.)
So, strtod seems to be one way to go. How about that nice sounding nan function?
vincent% cat nan2.c(I'm also working here under Linux. I'm not really sure what string I should drop in for the argument for nan. "hi!" also gives the same results as above. I'll stick with strtod for now.)
#include <math.h>
#include <stdio.h>
int main()
{
double x = nan("");
printf("%f\n", x);
printf("%d\n", (int)(x == x));
return 0;
}
vincent% gcc nan2.c -lm
vincent% ./a.out
0.000000
1
NaN
Is it safe to define a NaN using 0.0/0.0? Why doesn't the C standard define a function to return a quiet NaN? (Or does it??? I don't think so.) What do some of the open source implementations of the standard library's math functions do? Plan 9 sqrt.c -- ach, where does NaN() come from?
//
Well, well, well: I should've tried apropos nan right away:
man nan
But I'm still a little unclear on the portability of these. Is it safer from a portability perspective to use strtod?
\\
An article suggesting comparing floats in terms of the signed-magnitude numbers corresponding to the bit representations of the floats! Comparing floating point numbers. Cool!
//
Well, well, well: I should've tried apropos nan right away:
man nan
But I'm still a little unclear on the portability of these. Is it safer from a portability perspective to use strtod?
\\
An article suggesting comparing floats in terms of the signed-magnitude numbers corresponding to the bit representations of the floats! Comparing floating point numbers. Cool!
proportions p such that sum(round(100 * p)) != 100
> for (i in 1:10000) { u <- runif(3); p <- u / sum(u); k <- round(100 * p); if (sum(k) != 100) { print(p); print(k); break} }
[1] 0.03470525 0.45335042 0.51194434
[1] 3 45 51
> c(0.03470525, 0.45335042, 0.51194434)
[1] 0.03470525 0.45335042 0.51194434
> p <- c(0.03470525, 0.45335042, 0.51194434)
> sum(round(100 * p))
[1] 99
> p <- c(0.035, 0.45, 0.515)
> sum(round(100 * p))
[1] 101
> sum(p)
[1] 1
> 1 - sum(p)
[1] 0
[1] 0.03470525 0.45335042 0.51194434
[1] 3 45 51
> c(0.03470525, 0.45335042, 0.51194434)
[1] 0.03470525 0.45335042 0.51194434
> p <- c(0.03470525, 0.45335042, 0.51194434)
> sum(round(100 * p))
[1] 99
> p <- c(0.035, 0.45, 0.515)
> sum(round(100 * p))
[1] 101
> sum(p)
[1] 1
> 1 - sum(p)
[1] 0
Friday, June 6, 2008
partition number according to proportions
/**Earlier I had implemented this using only the second loop, now only used conditionally, with difference that I first rounded remaining * proportions[i] before truncating it to an int. However, this caused problems with too many points getting allocated, leading to a negative remainder and counts[0] getting an invalid value. Switching to simply truncating to zero, however, led us to sometimes not get exact results even when they were available. Eg, since (int) (97 * 0.5) = 48, the code under the if statement above divides 100 into (26, 49, 25) given proportions (0.25, 0.5, 0.25) rather (25, 50, 25) as one would hope. Hence, I have added the first loop and delegated the "safer" code to be called only in case of emergencies.
* On exit,
* counts[k] = number of points assigned to kth class,
* k = 0:(numClasses - 1) out of numPoints. Ensures that counts[k] > 0
* for every k while also sum(counts) = numPoints.
*/
void proportionsToCounts(const double* proportions,
int numClasses,
int numPoints,
int* counts)
{
int total = 0;
int numEmpty = 0;
int i;
assert(numPoints >= numClasses);
for (i = 0; i < numClasses; ++i) {
counts[i] = (int) round(numPoints * proportions[i]);
total += counts[i];
if (!counts[i]) {
++numEmpty;
}
}
if (numEmpty > 0 || total != numPoints) {
const double remaining = numPoints - numClasses;
int assigned = 0;
for (i = 1; i < numClasses; ++i) {
const int extra = (int) (remaining * proportions[i]);
assigned += extra;
counts[i] = 1 + extra;
}
counts[0] = 1 + numPoints - numClasses - assigned;
}
}
I'm sure there's a better way to do this though, but the above is probably more than good enough for my purposes.
Wednesday, June 4, 2008
Working with dates
Our cat is supposed to receive medicine every day for 60 days and then every other day, starting April 7. Working in Python:
>>> import datetime
>>> start = datetime.date(2008, 4, 7)
>>> d = start + datetime.timedelta(days=60)
>>> d
datetime.date(2008, 6, 6)
>>> d.ctime()
'Fri Jun 6 00:00:00 2008'
>>> import datetime
>>> start = datetime.date(2008, 4, 7)
>>> d = start + datetime.timedelta(days=60)
>>> d
datetime.date(2008, 6, 6)
>>> d.ctime()
'Fri Jun 6 00:00:00 2008'
Subscribe to:
Posts (Atom)