0

I want to do move through a loop and save a value at particular time intervals. I was thinking of something with this form:

    t <- 0
    t_end <- 10
    time_step <- 0.01
    record_interval <- 1
    while (t <= t_end){
        if (t %% record_interval == 0) print(t)
        t <- t + time_step
    }

But of course doing it this way fails due to machine precision issues.

I can do:

if (isTRUE(all.equal(t %% record_interval,0, tolerance = time_step*0.1))) { ...

But even this fails because sometimes it gives a modulo of record_interval rather than 0.

So, I can run my code with an or statement, using the above and also checking if the modulo is equal to record_interval, but that's incredibly ugly. I am sure there is an obvious, easy way to solve this problem but I am at a loss. I don't want to introduce an unnecessary integer counter (the all.equal part works, it's just not pretty, so that seems less bad), and I want to be able to change time_step and record_interval depending upon needs.

2
  • 2
    General approach: t_rolling <- t_rolling + time_step; if (t_rolling > record_interval) { print(t); t_rolling <- 0 } Commented Dec 1, 2023 at 14:53
  • 1
    Yeah, that's the right answer. I teach (not computer science!) and had thought to use this also to introduce the modulo operator--and look, I could toss in a little about tolerance as well!--but your way is much cleaner and is the clear way to do it if you're not caught up with modulo. I'll just do it this way instead. Thanks!
    – dchauri
    Commented Dec 1, 2023 at 16:06

2 Answers 2

0

One option would be to use tidyverse to create a new column called of your hundredths value, filter the data to the interval you want, then remove the new column.

# Load tidyverse
library(tidyverse)

# Create example data
dat <- data.frame(
  t = seq(0,10,0.01)
)

head(dat)
#>      t
#> 1 0.00
#> 2 0.01
#> 3 0.02
#> 4 0.03
#> 5 0.04
#> 6 0.05

# Create new column, filter the time interval you want, then remove the new column
dat2 <- dat %>%
  mutate(hundredths = floor(t * 100) %% 10) %>%
  filter(hundredths == 7) %>%
  select(-hundredths)

head(dat2)
#>      t
#> 1 0.07
#> 2 0.17
#> 3 0.27
#> 4 0.37
#> 5 0.47
#> 6 0.57

Created on 2023-12-01 with reprex v2.0.2

3
  • Unfortunately this suffers from the same problem I had originally, but it doesn't show up if you construct t using seq(). I ran the code first as you suggested, and it worked, and then I constructed t by sequentially adding the 0.01 time_step, and got the same result, with tail(dat2$t) giving [99] 9.81; [100] 9.91; [101] 10.01; [102] 100.00 . I couldn't get my code to format in the comment section (sorry, I'm new, and I haven't figured out the formatting), unfortuantely
    – dchauri
    Commented Dec 1, 2023 at 16:48
  • @dchauri I do not fully understand the issue you are seeking assistance with. Perhaps you can add some output of what your ideal output would look like? I will keep my answer posted so others do not take the same approach. Also, when you add a comment, there is a help button below the "Add comment" button that shows you how to add code to your comment (i.e., bracket your code with ` ).
    – tassones
    Commented Dec 1, 2023 at 16:59
  • Here is what I tried: time_step <- 0.01 t_temp <- 0 t <- c() while(t_temp <= 100){ t_temp <- t_temp + time_step t <- c(t_vec, t_temp) } dat <- data.frame(t) dat2 <- dat %>% mutate(hundredths = floor(t * 100) %% 10) %>% filter(hundredths == 0) %>% select(-hundredths) Here's what I got: > tail(dat2) t 97 9.61 98 9.71 99 9.81 100 9.91 101 10.01 102 100.00 I expected what I got when I ran your code: > tail(dat2) t 94 9.5 95 9.6 96 9.7 97 9.8 98 9.9 99 10.0
    – dchauri
    Commented Dec 1, 2023 at 21:04
0

You can get around the precision issue by just adding a rolling variable and resetting it when you hit the point you save the value:

t_rolling <- t_rolling + time_step; if (t_rolling > record_interval) { print(t); t_rolling <- 0 }

Thanks for the helpful responses!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.