Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by smirlianos · Dec 07, 2015 at 02:37 PM · floatdecimalzero

float adds decimal points over time

Hello, I have this script that is supposed to instantiate an object 10 times, every time 1.74 units up. The problem is that it isn't 1.74 every time, but something a little bit different, so the objects spawn on those y cordinates:

  • -17.4

  • -15.66

  • -13.92

  • -12.18

  • -10.44

  • -8.700001 (Here it starts getting weird, by adding 0.000001)

  • -6.960001

  • -5.220001

  • -3.480001

  • -1.740001

  • -1.192093e-06 (Here it is not 0, so I can not check on the IF statement)

         var posY : float = -17.4;
         var posX : int = 0;
         for(var i : int = 0; i <= 10; i++)
         {
             if(posY == 0)
             {
                 continue;
                 Debug.Log("Never goes here");
             }
             inst = Instantiate(par, Vector3(posX, posY, transform.position.z), transform.rotation);
             posX ++;
             posY += 1.74;
         }
     
     
    
    
    
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image maccabbe · Dec 07, 2015 at 02:59 PM 1
Share

Floats

  1. Have a limited precision

  2. Are stored as binary numbers on computers

Due to being binary 1.74 has to be converted from decimal. There's no exact way to represent 74/100 in binary so the float just rounds the number to a few significant figures. These errors accumulate and can become obvious.

The is analagous to how you would represent 1/3 in decimal. If you could have 3 significant figures you would use 0.333. Going down from 1 to 0 your values would be 1.000, 0.667, 0.334, 0.001.

There are very few situation where you should be comparing floats using ==.

avatar image saschandroid · Dec 07, 2015 at 03:13 PM 1
Share

You could use ints for adding up the posY (start with -1740 and adding 174) and divide it by 100 only when actually instantiating the gameobject (something like (float)posY / 100 ... I don't know for js) and see if this is working better.

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by wibble82 · Dec 07, 2015 at 03:03 PM

Hi there

I answered a similar question here earlier:

http://answers.unity3d.com/questions/1108438/how-to-instantiate-prefabs-at-certain-times.html#answer-1108590

Basically, floating point numbers are simply not accurate and there's no way around this. Remember that internally they're stored as binary values, so it's entirely possible there won't be a precise representation for -17.4. What you're seeing is a very gradual drift, which is expected behaviour. It's probably insignficant from the point of what the user sees, but precise comparisons often don't work.

The most common way of correcting your code would be:

 //check the absolute (i.e. postive) value of posY is almost exactly 0
 if(Mathf.Abs(posY) <= 0.00001f)
          {
              continue;
              Debug.Log("Never goes here");
          }

Typically its best to avoid situations in which you need to compare a floating point numbers in this way, but when you have to do it, that's the best approach to use.

Note that a more reliable way to write your code might be:

      var startPosY : float = -17.4;
      for(var i : int = 0; i <= 10; i++)
      {
          var posX : int = i;
          var posY : float = startPosY + i*1.74;
 
          if(Mathf.Abs(posY) < 0.00001)
          {
              continue;
              Debug.Log("Never goes here");
          }
          inst = Instantiate(par, Vector3(posX, posY, transform.position.z), transform.rotation);
      }

(sorry if that doesn't compile - I'm a c# guy!)

By avoiding repeated additions that gradually get less accurate, I've ensured in this example that my numbers won't drift. There will still be inaccuracies, but they won't gradually get higher and higher and higher. I'm not entirely clear why you need the if statement at all, but maybe you just added it as an example?

Hope that helps

-Chris

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image smirlianos · Dec 07, 2015 at 03:33 PM 0
Share

Thanks!

I found a workaround! I used:

 posY = System.$$anonymous$$ath.Round(posY, 2)
avatar image wibble82 smirlianos · Dec 07, 2015 at 03:45 PM 1
Share

Heheh - I guess that works, though the careful programmer in me disprove :) Lets hope you never want to increment by 1.745 every frame!

avatar image
1

Answer by troien · Dec 07, 2015 at 03:33 PM

Although the other answer will probably work, I'll add this one, as the docs specify it as the way to check for float equality (Which is what you are trying to do)...

Use Mathf.Approximately instead of ==.

Like so: (ps. I believe adding your log after continue, should actually give you the warning in the console that it will never be called). as continue will skip it and continue with the next loop iteration ;)

 if (Mathf.Approximately(posY, 0))
 {
     Debug.Log("does go here");
     continue;
     Debug.Log("Never goes here");
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

33 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Angular Velocity to zero 0 Answers

How to get type double to vector3? 0 Answers

Float without comma 1 Answer

Make a float display 10:07 instead of 10.7 2 Answers

Is there an int based class/struct like Vector2? 4 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges