When I run the following commands,
(0..20).step(0.1) do |n|
puts n
end
I get the following return:
0.0
0.1
0.2
0.30000000000000004
0.4
0.5
0.6000000000000001
0.7000000000000001
0.8
0.9
1.0
1.1
1.2000000000000002
1.3
1.4000000000000001
1.5
1.6
1.7000000000000002
...
What is the best way to avoid this roundoff error?
Update:
My question about why this occurs has been previously answered here in another question, Is floating point math broken?, but I did not immediately find that.
You could cheat and avoid the stepping by 0.1 business:
(0..200).map { |n| n.to_f / 10 }
=> [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7,...]
Related
I am new to the promising language of Julia, in the hope that it will accelerate my stiff ordinary differential equations. Here is the thing:
1) The equation must be defined in matrix form, by using mass, damping, stiffness matrices outa Matlab with dimension 400x400. The common state-space represenation for 2nd order ODE's is implemented.
2) Apart from the linear dynamics, there are nonlinear forces acting, which depend on certain states of it. These forces must be defined inside the ode function.
However the state variables do not change at all, although the should, due to the inital conditions. Here is an example code, with smaller matrices, for prototyping:
#Load packages
using LinearAlgebra
using OrdinaryDiffEq
using DifferentialEquations
using Plots
# Define constant matrices (here generated for the example)
const M=Matrix{Float64}(I, 4, 4) # Mass matrix
const C=zeros(Float64, 4, 4) # Damping matrix
const K=[10.0 0.0 0.0 0.0; 0.0 7.0 0.0 0.0; 0.0 0.0 6.0 0.0;0.0 0.0 5.0 0.0] # Stiffness matrix
x0 = [0.0;0.0;0.0;0.0; 1.0; 1.0; 1.0; 1.0] # Initial conditions
tspan = (0.,1.0) # Simulation time span
#Define the underlying equation
function FourDOFoscillator(xdot,x,p,t)
xdot=[-inv(M)*C -inv(M)*K; Matrix{Float64}(I, 4, 4) zeros(Float64, 4, 4)]*x
end
#Pass to Solvers
prob = ODEProblem(FourDOFoscillator,x0,tspan)
sol = solve(prob,alg_hints=[:stiff],reltol=1e-8,abstol=1e-8)
plot(sol)
What am I missing?
Thanks
Betelgeuse
You're not mutating the output, and instead creating a new array. If you do xdot.= it works.
#Load packages
using LinearAlgebra
using OrdinaryDiffEq
using DifferentialEquations
using Plots
# Define constant matrices (here generated for the example)
const M=Matrix{Float64}(I, 4, 4) # Mass matrix
const C=zeros(Float64, 4, 4) # Damping matrix
const K=[10.0 0.0 0.0 0.0; 0.0 7.0 0.0 0.0; 0.0 0.0 6.0 0.0;0.0 0.0 5.0 0.0] # Stiffness matrix
x0 = [0.0;0.0;0.0;0.0; 1.0; 1.0; 1.0; 1.0] # Initial conditions
tspan = (0.,1.0) # Simulation time span
#Define the underlying equation
function FourDOFoscillator(xdot,x,p,t)
xdot.=[-inv(M)*C -inv(M)*K; Matrix{Float64}(I, 4, 4) zeros(Float64, 4, 4)]*x
end
#Pass to Solvers
prob = ODEProblem(FourDOFoscillator,x0,tspan)
sol = solve(prob,alg_hints=[:stiff],reltol=1e-8,abstol=1e-8)
plot(sol)
In Julia v0.5, how do you make a function which is like reshape but instead returns a view? ArrayViews.jl has a reshape_view function but it doesn't seem directly compatible with the new view function. I just want to reshape u to some tuple sizeu where I don't know the dimensions.
If you reshape a 'view', the output is a reshaped 'view'.
If your initial variable is a normal array, you can convert it to a view 'on the fly' during your function call.
There are no reallocations during this operation, as per your later comment: you can confirm this with the pointer function. The objects aren't the same, in the sense that they are interpreted as pointers to a different 'type', but the memory address is the same.
julia> A = ones(5,5,5); B = view(A, 2:4, 2:4, 2:4); C = reshape(B, 1, 27);
julia> is(B,C)
false
julia> pointer(B)
Ptr{Float64} #0x00007ff51e8b1ac8
julia> pointer(C)
Ptr{Float64} #0x00007ff51e8b1ac8
julia> C[1:5] = zeros(1,5);
julia> A[:,:,2]
5×5 Array{Float64,2}:
1.0 1.0 1.0 1.0 1.0
1.0 0.0 0.0 1.0 1.0
1.0 0.0 0.0 1.0 1.0
1.0 0.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0
I try to fit a linear model (and get the R^2) to the following test-data
0.0 0.0
1.0 1.0
2.0 2.0
3.0 3.1
I wrote the following code using scalanlp/breeze 0.12 :
import breeze.linalg.{DenseMatrix, DenseVector}
import breeze.stats.regression.leastSquares
val indep = DenseMatrix((1.0, 0.0), (1.0, 1.0), (1.0, 2.0), (1.0, 3.0))
val dep = DenseVector(0.0, 1.0, 2.0, 3.1)
val result = leastSquares(indep, dep)
println("intercept=" + result.coefficients.data(0))
println("slope=" + result.coefficients.data(1))
println("r^2=" + result.rSquared)
the output is:
intercept=-0.020000000000000018
slope=1.03
r^2=0.0014623322596666252
Intercept and slope are reasonable, but I don't understand R-squared, it should be close to 1!
Your vector of ones needs to come last not first. Hence the r^2 = 1-r_e^2 you expected.
EDIT: While what I said above is correct about switching around your vector of 1s. I'm still getting a horribly incorrect r-squared as well even using that. My slope and intercept are spot on though, much like yours. So... to the source code!
EDIT2: Known issue. Hasn't been fixed. shrug
As the title suggest, would hope to generate a random float in the range between 0.3 < x < 0.7.
I currently using while loop to check a random float whether its in that range. I was wondering whether there is a better method to do this.
0.3 + random-float 0.4 will give you 0.3 <= x < 0.7.
If you really don't want 0.3, I guess you can always loop that one out. I'm not sure if there is a better way.
Given a list of items x1 ... xn and associated probabilties p1 ... pn that sum up to 1 there's a well known procedure to select a random item with its associated proabability by sorting the list according to weight, choosing a random value between 1 and 0, and adding up to a culmination sum until it exceeds the value selected and return the item at this point.
So if we have x1 -> 0.5, x2 -> 0.3, x3 -> 0.2, if the randomly chosen value is less than 0.5 x1 will be chosen, if between 0.5 and 0.8, x2, and else x3.
This requires sorting so it needs O(nlogn) time. Is there anything more efficient than that?
I don't think you would actually need to sort the list for the algorithm to work.
x1 = 0.2, x2 = 0.7, x3 = 0.1
If you sort then you have:
x3: 0.0 to 0.1 = 10%
x1: 0.1 to 0.3 = 20%
x2: 0.3 to 1.0 = 70%
If you dont, you instead get:
x1: 0.0 to 0.2 = 20%
x2: 0.2 to 0.9 = 70%
x3: 0.9 to 1.0 = 10%
Just eliminating the sort and iterating through would make it O(n).