Search code examples
rsimulationnormal-distribution

R: Avoid floating point arithmetic when normalizing to sum 0


I need to pull a vector from a normal distribution and normalize it to sum 0, because I want to simulate the power with the pwr.rasch() function from the pwrRasch package. Sounds easy enough.

I create the vector like this:

set.seed(123)
itempars <- rnorm(n = 10, mean = 0, sd = 1.8)  

To normalize the parameters to 0, I subtract the sum of my vector off of the last element of the vector like this:

itempars[10] <- itempars[10] - sum(itempars)

When I type sum(itempars) it should be 0, but it's -8.326673e-17. How is it possible? How can I get it to 0? I tried to round already, but it only increases the sum.

I don't want to choose every Itemparameter by hand. Thanks in advance!

EDIT:

Obviously the reasion is floating-point arithmetic. But it's hard to imagine that there is no way around.

The error massage of pwr.rasch() is as follows:

Error in simul.rasch(eval(parse(text = ppar[[1]])), ipar[[1]]) : 
Item pararameters are not normalized to sum-0

Sadly, the function has poor documentation. When I estimate groupwise itemparameters with eRm's RM() function, which has an extra argument for normalizing to sum 0, it gives me a similar difference like in my example.

Any trick'd come in handy as I don't want to create more than 50 normal distributed itemparameters per hand. Even worse. If I understood floating-point arithemtic corretly this problem can appear with the use of doubles in general. It'd be extremely limitating if I'd only be able to use integers as itemparameters.


Solution

  • I downloaded the source code of the pwrRasch package and changed the if condition from

    if (all(round(unlist(lapply(ipar, sum)), 3) != 0)) {
    
        stop("Item pararameters are not normalized to sum-0")
    
    } 
    

    to

    if (all(round(unlist(lapply(ipar, sum)), 3) > 1e-5)) {
    
        stop("Item pararameters are not normalized to sum-0")
    
    }